diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml
index 358bafc5a7c80a6eba03c2fe39a4b91b118622e4..ca07033f9f7934b42d43588e183d63b3a4c35ec0 100644
--- a/Library/.rubocop.yml
+++ b/Library/.rubocop.yml
@@ -26,10 +26,6 @@ Cask/Desc:
   Description: 'Ensure that the desc stanza conforms to various content and style checks.'
   Enabled: true
 
-Cask/HomepageMatchesUrl:
-  Description: 'Ensure that the homepage and url match, otherwise add a comment. More info at https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-a-comment'
-  Enabled: true
-
 Cask/HomepageUrlTrailingSlash:
   Description: 'Ensure that the homepage url has a slash after the domain name.'
   Enabled: true
diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb
index 1cc322e50730454122767afa8f93740e48bb3477..22980038aabcf406cbb6045b76be228390bdb9f9 100644
--- a/Library/Homebrew/cask/audit.rb
+++ b/Library/Homebrew/cask/audit.rb
@@ -52,6 +52,9 @@ module Cask
       check_sha256
       check_desc
       check_url
+      check_unnecessary_verified
+      check_missing_verified
+      check_no_match
       check_generic_artifacts
       check_token_valid
       check_token_bad_words
@@ -345,6 +348,80 @@ module Cask
       bad_url_format?(/osd/, [%r{\Ahttps?://([^/]+.)?dl\.osdn\.jp/}])
     end
 
+    def homepage
+      URI(cask.homepage.to_s).host
+    end
+
+    def domain
+      URI(cask.url.to_s).host
+    end
+
+    def url_match_homepage?
+      host = cask.url.to_s.downcase
+      host_uri = URI(host)
+      host = if host.match?(/:\d/) && host_uri.port != 80
+        "#{host_uri.host}:#{host_uri.port}"
+      else
+        host_uri.host
+      end
+      home = homepage.downcase
+      if (split_host = host.split(".")).length >= 3
+        host = split_host[-2..].join(".")
+      end
+      if (split_home = homepage.split(".")).length >= 3
+        home = split_home[-2..].join(".")
+      end
+      host == home
+    end
+
+    def strip_url_scheme(url)
+      url.sub(%r{^.*://(www\.)?}, "")
+    end
+
+    def url_from_verified
+      cask.url.verified.sub(%r{^https?://}, "")
+    end
+
+    def verified_matches_url?
+      strip_url_scheme(cask.url.to_s).start_with?(url_from_verified)
+    end
+
+    def verified_present?
+      cask.url.verified.present?
+    end
+
+    def url_includes_file?
+      cask.url.to_s.start_with?("file://")
+    end
+
+    def check_unnecessary_verified
+      return unless verified_present?
+      return unless url_match_homepage?
+      return unless verified_matches_url?
+
+      add_warning "The URL's #{domain} matches the homepage #{homepage}, " \
+                  "the `verified` parameter of the `url` stanza is unnecessary. " \
+                  "See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-verified"
+    end
+
+    def check_missing_verified
+      return if url_includes_file?
+      return if url_match_homepage?
+      return if verified_present?
+
+      add_warning "#{domain} does not match #{homepage}, a `verified` parameter of the `url` has to be added. " \
+                  " See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-verified"
+    end
+
+    def check_no_match
+      return if url_match_homepage?
+      return unless verified_present?
+      return if !url_match_homepage? && verified_matches_url?
+
+      add_warning "#{url_from_verified} does not match #{strip_url_scheme(cask.url.to_s)}. " \
+                  "See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-verified"
+    end
+
     def check_generic_artifacts
       cask.artifacts.select { |a| a.is_a?(Artifact::Artifact) }.each do |artifact|
         unless artifact.target.absolute?
diff --git a/Library/Homebrew/cask/url.rb b/Library/Homebrew/cask/url.rb
index 5a6bb0d1c9eaae7283a0beba76dd7c8691c1e49a..7bb6d5adf71e9528f79a67dd8f481c2e7f105348 100644
--- a/Library/Homebrew/cask/url.rb
+++ b/Library/Homebrew/cask/url.rb
@@ -8,7 +8,7 @@ class URL
   extend T::Sig
 
   attr_reader :uri, :specs,
-              :using,
+              :verified, :using,
               :tag, :branch, :revisions, :revision,
               :trust_cert, :cookies, :referer, :header, :user_agent,
               :data
@@ -19,6 +19,7 @@ class URL
   sig do
     params(
       uri:        T.any(URI::Generic, String),
+      verified:   T.nilable(String),
       using:      T.nilable(Symbol),
       tag:        T.nilable(String),
       branch:     T.nilable(String),
@@ -34,6 +35,7 @@ class URL
   end
   def initialize(
     uri,
+    verified: nil,
     using: nil,
     tag: nil,
     branch: nil,
@@ -49,6 +51,7 @@ class URL
     @uri = URI(uri)
 
     specs = {}
+    specs[:verified]   = @verified   = verified
     specs[:using]      = @using      = using
     specs[:tag]        = @tag        = tag
     specs[:branch]     = @branch     = branch
diff --git a/Library/Homebrew/rubocops/cask/homepage_matches_url.rb b/Library/Homebrew/rubocops/cask/homepage_matches_url.rb
deleted file mode 100644
index 83f112b5e8b4f3890a001c40f1801a57a77af942..0000000000000000000000000000000000000000
--- a/Library/Homebrew/rubocops/cask/homepage_matches_url.rb
+++ /dev/null
@@ -1,180 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-require "forwardable"
-
-module RuboCop
-  module Cop
-    module Cask
-      # This cop checks that a cask's homepage matches the download URL,
-      # or if it doesn't, checks if a comment in the form
-      # `# example.com was verified as official when first introduced to the cask`
-      # is present.
-      class HomepageMatchesUrl < Cop
-        extend Forwardable
-        include CaskHelp
-
-        REFERENCE_URL =
-          "https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/" \
-          "cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-a-comment"
-
-        COMMENT_FORMAT = /# [^ ]+ was verified as official when first introduced to the cask/.freeze
-
-        MSG_NO_MATCH = "`%<url>s` does not match `%<full_url>s`"
-
-        MSG_MISSING = ("`%<domain>s` does not match `%<homepage>s`, a comment has to be added " \
-                      "above the `url` stanza. For details, see " + REFERENCE_URL).freeze
-
-        MSG_WRONG_FORMAT = ("`%<comment>s` does not match the expected comment format. " \
-                           "For details, see " + REFERENCE_URL).freeze
-
-        MSG_UNNECESSARY = "The URL's domain `%<domain>s` matches the homepage `%<homepage>s`, " \
-                          "the comment above the `url` stanza is unnecessary"
-
-        def on_cask(cask_block)
-          @cask_block = cask_block
-          return unless homepage_stanza
-
-          add_offenses
-        end
-
-        private
-
-        attr_reader :cask_block
-
-        def_delegators :cask_block, :cask_node, :toplevel_stanzas,
-                       :sorted_toplevel_stanzas
-
-        def add_offenses
-          toplevel_stanzas.select(&:url?).each do |url|
-            next if add_offense_unnecessary_comment(url)
-            next if add_offense_missing_comment(url)
-            next if add_offense_no_match(url)
-            next if add_offense_wrong_format(url)
-          end
-        end
-
-        def add_offense_unnecessary_comment(stanza)
-          return unless comment?(stanza)
-          return unless url_match_homepage?(stanza)
-          return unless comment_matches_format?(stanza)
-          return unless comment_matches_url?(stanza)
-
-          comment = comment(stanza).loc.expression
-          add_offense(comment,
-                      location: comment,
-                      message:  format(MSG_UNNECESSARY, domain: domain(stanza), homepage: homepage))
-        end
-
-        def add_offense_missing_comment(stanza)
-          return if url_match_homepage?(stanza)
-          return if !url_match_homepage?(stanza) && comment?(stanza)
-
-          range = stanza.source_range
-          url_domain = domain(stanza)
-          add_offense(range, location: range, message: format(MSG_MISSING, domain: url_domain, homepage: homepage))
-        end
-
-        def add_offense_no_match(stanza)
-          return if url_match_homepage?(stanza)
-          return unless comment?(stanza)
-          return if !url_match_homepage?(stanza) && comment_matches_url?(stanza)
-
-          comment = comment(stanza).loc.expression
-          add_offense(comment,
-                      location: comment,
-                      message:  format(MSG_NO_MATCH, url: url_from_comment(stanza), full_url: full_url(stanza)))
-        end
-
-        def add_offense_wrong_format(stanza)
-          return if url_match_homepage?(stanza)
-          return unless comment?(stanza)
-          return if comment_matches_format?(stanza)
-
-          comment = comment(stanza).loc.expression
-          add_offense(comment,
-                      location: comment,
-                      message:  format(MSG_WRONG_FORMAT, comment: comment(stanza).text))
-        end
-
-        def comment?(stanza)
-          !stanza.comments.empty?
-        end
-
-        def comment(stanza)
-          stanza.comments.last
-        end
-
-        def comment_matches_format?(stanza)
-          comment(stanza).text =~ COMMENT_FORMAT
-        end
-
-        def url_from_comment(stanza)
-          comment(stanza).text
-                         .sub(/[^ ]*# ([^ ]+) .*/, '\1')
-        end
-
-        def comment_matches_url?(stanza)
-          full_url(stanza).include?(url_from_comment(stanza))
-        end
-
-        def strip_url_scheme(url)
-          url.sub(%r{^.*://(www\.)?}, "")
-        end
-
-        def domain(stanza)
-          strip_url_scheme(extract_url(stanza)).gsub(%r{^([^/]+).*}, '\1')
-        end
-
-        def extract_url(stanza)
-          string = stanza.stanza_node.children[2]
-          return string.str_content if string.str_type?
-
-          string.to_s.gsub(%r{.*"([a-z0-9]+://[^"]+)".*}m, '\1')
-        end
-
-        def url_match_homepage?(stanza)
-          host = extract_url(stanza).downcase
-          host_uri = begin
-            URI(remove_non_ascii(host))
-          rescue URI::InvalidURIError
-            # Can't check if we can't parse.
-            nil
-          end
-
-          return true if host_uri.blank?
-
-          host = if host.match?(/:\d/) && host_uri.port != 80
-            "#{host_uri.host}:#{host_uri.port}"
-          else
-            host_uri.host
-          end
-          home = homepage.downcase
-          if (split_host = host.split(".")).length >= 3
-            host = split_host[-2..].join(".")
-          end
-          if (split_home = homepage.split(".")).length >= 3
-            home = split_home[-2..].join(".")
-          end
-          host == home
-        end
-
-        def full_url(stanza)
-          strip_url_scheme(extract_url(stanza))
-        end
-
-        def homepage
-          URI(remove_non_ascii(extract_url(homepage_stanza))).host
-        end
-
-        def homepage_stanza
-          toplevel_stanzas.find(&:homepage?)
-        end
-
-        def remove_non_ascii(string)
-          string.gsub(/\P{ASCII}/, "")
-        end
-      end
-    end
-  end
-end
diff --git a/Library/Homebrew/rubocops/rubocop-cask.rb b/Library/Homebrew/rubocops/rubocop-cask.rb
index fbba19daf4a26d1caa5b8aeca435e11bf1e4bb7f..3e0a2c457865b075bffbe90c10aff58c4cdd05b4 100644
--- a/Library/Homebrew/rubocops/rubocop-cask.rb
+++ b/Library/Homebrew/rubocops/rubocop-cask.rb
@@ -13,7 +13,6 @@ require "rubocops/cask/extend/node"
 require "rubocops/cask/mixin/cask_help"
 require "rubocops/cask/mixin/on_homepage_stanza"
 require "rubocops/cask/desc"
-require "rubocops/cask/homepage_matches_url"
 require "rubocops/cask/homepage_url_trailing_slash"
 require "rubocops/cask/no_dsl_version"
 require "rubocops/cask/stanza_order"
diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb
index 285c6ec3cc662fb554be1785b589f02484a9df85..9477a16f2b3dd81e5d33868b094691d4abca8918 100644
--- a/Library/Homebrew/test/cask/audit_spec.rb
+++ b/Library/Homebrew/test/cask/audit_spec.rb
@@ -887,5 +887,80 @@ describe Cask::Audit, :cask do
         expect(subject).to pass
       end
     end
+
+    context "when the url matches the homepage" do
+      let(:cask_token) { "foo" }
+      let(:cask) do
+        tmp_cask cask_token.to_s, <<~RUBY
+          cask '#{cask_token}' do
+            version '1.0'
+            sha256 '8dd95daa037ac02455435446ec7bc737b34567afe9156af7d20b2a83805c1d8a'
+            url 'https://foo.brew.sh/foo.zip'
+            name 'Audit'
+            desc 'Audit Description'
+            homepage 'https://foo.brew.sh'
+            app 'Audit.app'
+          end
+        RUBY
+      end
+
+      it { is_expected.to pass }
+    end
+
+    context "when the url does not match the homepage" do
+      let(:cask_token) { "foo" }
+      let(:cask) do
+        tmp_cask cask_token.to_s, <<~RUBY
+          cask '#{cask_token}' do
+            version '1.8.0_72,8.13.0.5'
+            sha256 '8dd95daa037ac02455435446ec7bc737b34567afe9156af7d20b2a83805c1d8a'
+            url 'https://brew.sh/foo.zip'
+            name 'Audit'
+            desc 'Audit Description'
+            homepage 'https://foo.example.org'
+            app 'Audit.app'
+          end
+        RUBY
+      end
+
+      it { is_expected.to warn_with(/a `verified` parameter of the `url` has to be added./) }
+    end
+
+    context "when the url does not match the homepage with verified" do
+      let(:cask_token) { "foo" }
+      let(:cask) do
+        tmp_cask cask_token.to_s, <<~RUBY
+          cask '#{cask_token}' do
+            version '1.8.0_72,8.13.0.5'
+            sha256 '8dd95daa037ac02455435446ec7bc737b34567afe9156af7d20b2a83805c1d8a'
+            url 'https://brew.sh/foo.zip', verified: 'brew.sh'
+            name 'Audit'
+            desc 'Audit Description'
+            homepage 'https://foo.example.org'
+            app 'Audit.app'
+          end
+        RUBY
+      end
+
+      it { is_expected.to pass }
+    end
+
+    context "when there is no homepage" do
+      let(:cask_token) { "foo" }
+      let(:cask) do
+        tmp_cask cask_token.to_s, <<~RUBY
+          cask '#{cask_token}' do
+            version '1.8.0_72,8.13.0.5'
+            sha256 '8dd95daa037ac02455435446ec7bc737b34567afe9156af7d20b2a83805c1d8a'
+            url 'https://brew.sh/foo.zip'
+            name 'Audit'
+            desc 'Audit Description'
+            app 'Audit.app'
+          end
+        RUBY
+      end
+
+      it { is_expected.to fail_with(/a homepage stanza is required/) }
+    end
   end
 end
diff --git a/Library/Homebrew/test/rubocops/cask/homepage_matches_url_spec.rb b/Library/Homebrew/test/rubocops/cask/homepage_matches_url_spec.rb
deleted file mode 100644
index 4ef084f3e1182954717a7293cca35784b7e23e81..0000000000000000000000000000000000000000
--- a/Library/Homebrew/test/rubocops/cask/homepage_matches_url_spec.rb
+++ /dev/null
@@ -1,216 +0,0 @@
-# typed: false
-# frozen_string_literal: true
-
-require "rubocops/rubocop-cask"
-require "test/rubocops/cask/shared_examples/cask_cop"
-
-describe RuboCop::Cop::Cask::HomepageMatchesUrl do
-  include CaskCop
-
-  subject(:cop) { described_class.new }
-
-  context "when the url matches the homepage and there is no comment" do
-    let(:source) do
-      <<-CASK.undent
-        cask 'foo' do
-          url 'https://foo.brew.sh/foo.zip'
-          homepage 'https://foo.brew.sh'
-        end
-      CASK
-    end
-
-    include_examples "does not report any offenses"
-  end
-
-  context "when the url matches the homepage and the url stanza has " \
-          "a referrer and no interpolation" do
-    let(:source) do
-      <<-CASK.undent
-        cask 'foo' do
-          url 'https://foo.brew.sh/foo.zip',
-              referrer: 'https://brew.sh/foo/'
-          homepage 'https://foo.brew.sh'
-        end
-      CASK
-    end
-
-    include_examples "does not report any offenses"
-  end
-
-  context "when the url matches the homepage and the url stanza has " \
-          "a referrer and interpolation" do
-    let(:source) do
-      <<-CASK.undent
-        cask 'foo' do
-          version '1.8.0_72,8.13.0.5'
-          url "https://foo.brew.sh/foo-\#{version.after_comma}-\#{version.minor}.\#{version.patch}.\#{version.before_comma.sub(\%r{.*_}, '')}.zip",
-              referrer: 'https://brew.sh/foo/'
-          homepage 'https://foo.brew.sh'
-        end
-      CASK
-    end
-
-    include_examples "does not report any offenses"
-  end
-
-  context "when the url matches the homepage but there is a comment " \
-          "which does not match the url" do
-    let(:source) do
-      <<-CASK.undent
-        cask 'foo' do
-          # this is just a comment with information
-          url 'https://brew.sh/foo.zip'
-          homepage 'https://brew.sh'
-        end
-      CASK
-    end
-
-    include_examples "does not report any offenses"
-  end
-
-  context "when the url matches the homepage " \
-          "but there is a comment matching the url" do
-    let(:source) do
-      <<-CASK.undent
-        cask 'foo' do
-          # foo.brew.sh was verified as official when first introduced to the cask
-          url 'https://foo.brew.sh/foo.zip'
-          homepage 'https://foo.brew.sh'
-        end
-      CASK
-    end
-    let(:expected_offenses) do
-      [{
-        message:  "The URL's domain `foo.brew.sh` matches the homepage " \
-                 "`foo.brew.sh`, the comment above the `url` stanza is " \
-                 "unnecessary",
-        severity: :convention,
-        line:     2,
-        column:   2,
-        source:   "# foo.brew.sh was verified as official when " \
-                "first introduced to the cask",
-      }]
-    end
-
-    include_examples "reports offenses"
-  end
-
-  context "when the url does not match the homepage" do
-    context "when there is a comment matching the url " \
-            "but not matching the expected format" do
-      let(:source) do
-        <<-CASK.undent
-          cask 'foo' do
-            # brew.sh was verified as official
-            url 'https://brew.sh/foo.zip'
-            homepage 'https://foo.example.org'
-          end
-        CASK
-      end
-      let(:expected_offenses) do
-        [{
-          message:  "`# brew.sh was verified as official` does not " \
-                   "match the expected comment format. For details, see " \
-                  "https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/" \
-                  "cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-a-comment",
-          severity: :convention,
-          line:     2,
-          column:   2,
-          source:   "# brew.sh was verified as official",
-        }]
-      end
-
-      include_examples "reports offenses"
-    end
-
-    context "when there is a comment matching the url " \
-            "and does not have slashes" do
-      let(:source) do
-        <<-CASK.undent
-          cask 'foo' do
-            # brew.sh was verified as official when first introduced to the cask
-            url 'https://brew.sh/foo.zip'
-            homepage 'https://foo.example.org'
-          end
-        CASK
-      end
-
-      include_examples "does not report any offenses"
-    end
-
-    context "when there is a comment matching the url and has slashes" do
-      let(:source) do
-        <<-CASK.undent
-          cask 'foo' do
-            # brew.sh/vendor/app was verified as official when first introduced to the cask
-            url 'https://downloads.brew.sh/vendor/app/foo.zip'
-            homepage 'https://vendor.example.org/app/'
-          end
-        CASK
-      end
-
-      include_examples "does not report any offenses"
-    end
-
-    context "when there is a comment which does not match the url" do
-      let(:source) do
-        <<-CASK.undent
-          cask 'foo' do
-            # brew.sh was verified as official when first introduced to the cask
-            url 'https://example.org/foo.zip'
-            homepage 'https://foo.brew.sh'
-          end
-        CASK
-      end
-      let(:expected_offenses) do
-        [{
-          message:  "`brew.sh` does not match `example.org/foo.zip`",
-          severity: :convention,
-          line:     2,
-          column:   2,
-          source:   "# brew.sh was verified as official when " \
-                  "first introduced to the cask",
-        }]
-      end
-
-      include_examples "reports offenses"
-    end
-
-    context "when the comment is missing" do
-      let(:source) do
-        <<-CASK.undent
-          cask 'foo' do
-            url 'https://brew.sh/foo.zip'
-            homepage 'https://example.org'
-          end
-        CASK
-      end
-      let(:expected_offenses) do
-        [{
-          message:  "`brew.sh` does not match `example.org`, a comment " \
-                   "has to be added above the `url` stanza. For details, see " \
-                   "https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/" \
-                   "cask_language_reference/stanzas/url.md#when-url-and-homepage-hostnames-differ-add-a-comment",
-          severity: :convention,
-          line:     2,
-          column:   2,
-          source:   "url 'https://brew.sh/foo.zip'",
-        }]
-      end
-
-      include_examples "reports offenses"
-    end
-  end
-
-  context "when there is no homepage" do
-    let(:source) do
-      <<-CASK.undent
-        cask 'foo' do
-          url 'https://brew.sh/foo.zip'
-        end
-      CASK
-    end
-
-    include_examples "does not report any offenses"
-  end
-end
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-relative-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-relative-target.rb
index 576f4de472246719cd7b8f4c9c1bb196c5dd2486..e804ffd270dff6eca168a56e0cbaded97228c632 100644
--- a/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-relative-target.rb
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-relative-target.rb
@@ -1,3 +1,11 @@
 cask "generic-artifact-relative-target" do
+  version "1.2.3"
+  sha256 "d5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2"
+
+  url "file://#{TEST_FIXTURE_DIR}/cask/AppWithBinary.zip"
+  name "With Binary"
+  desc "Cask with a binary stanza"
+  homepage "https://brew.sh/with-binary"
+
   artifact "Caffeine.app", target: "Caffeine.app"
 end