Merge pull request #5033 from amyspark/gitjiro-improved

Cask: complete Git-Jiro's HTTPS audit check
This commit is contained in:
Mike McQuaid 2018-11-24 11:43:09 +00:00 committed by GitHub
commit 2562d270b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 69 additions and 39 deletions

View File

@ -1,6 +1,7 @@
require "cask/checkable"
require "cask/download"
require "digest"
require "utils/curl"
require "utils/git"
module Cask
@ -30,6 +31,7 @@ module Cask
check_generic_artifacts
check_token_conflicts
check_download
check_https_availability
check_single_pre_postflight
check_single_uninstall_zap
check_untrusted_pkg
@ -317,5 +319,19 @@ module Cask
rescue => e
add_error "download not possible: #{e.message}"
end
def check_https_availability
return unless download
if !cask.url.blank? && !cask.url.using
check_url_for_https_availability(cask.url, user_agents: [cask.url.user_agent])
end
check_url_for_https_availability(cask.appcast) unless cask.appcast.blank?
check_url_for_https_availability(cask.homepage) unless cask.homepage.blank?
end
def check_url_for_https_availability(url_to_check, user_agents: [:default])
problem = curl_check_http_content(url_to_check.to_s, user_agents: user_agents)
add_error problem if problem
end
end
end

View File

@ -8,13 +8,13 @@ describe Cask::Cmd::Home, :cask do
it_behaves_like "a command that handles invalid options"
it "opens the homepage for the specified Cask" do
expect(described_class).to receive(:open_url).with("https://example.com/local-caffeine")
expect(described_class).to receive(:open_url).with("https://example.com")
described_class.run("local-caffeine")
end
it "works for multiple Casks" do
expect(described_class).to receive(:open_url).with("https://example.com/local-caffeine")
expect(described_class).to receive(:open_url).with("https://example.com/local-transmission")
expect(described_class).to receive(:open_url).with("https://example.com")
expect(described_class).to receive(:open_url).with("https://example.com")
described_class.run("local-caffeine", "local-transmission")
end

View File

@ -10,7 +10,7 @@ describe Cask::Cmd::Info, :cask do
described_class.run("local-caffeine")
}.to output(<<~EOS).to_stdout
local-caffeine: 1.2.3
https://example.com/local-caffeine
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/local-caffeine.rb
==> Name
@ -39,7 +39,7 @@ describe Cask::Cmd::Info, :cask do
let(:expected_output) {
<<~EOS
local-caffeine: 1.2.3
https://example.com/local-caffeine
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/local-caffeine.rb
==> Name
@ -47,7 +47,7 @@ describe Cask::Cmd::Info, :cask do
==> Artifacts
Caffeine.app (App)
local-transmission: 2.61
https://example.com/local-transmission
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/local-transmission.rb
==> Name
@ -69,7 +69,7 @@ describe Cask::Cmd::Info, :cask do
described_class.run("with-caveats")
}.to output(<<~EOS).to_stdout
with-caveats: 1.2.3
https://example.com/local-caffeine
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/with-caveats.rb
==> Name
@ -95,7 +95,7 @@ describe Cask::Cmd::Info, :cask do
described_class.run("with-conditional-caveats")
}.to output(<<~EOS).to_stdout
with-conditional-caveats: 1.2.3
https://example.com/local-caffeine
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/with-conditional-caveats.rb
==> Name
@ -110,7 +110,7 @@ describe Cask::Cmd::Info, :cask do
described_class.run("with-languages")
}.to output(<<~EOS).to_stdout
with-languages: 1.2.3
https://example.com/local-caffeine
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/with-languages.rb
==> Name
@ -127,7 +127,7 @@ describe Cask::Cmd::Info, :cask do
described_class.run("without-languages")
}.to output(<<~EOS).to_stdout
without-languages: 1.2.3
https://example.com/local-caffeine
https://example.com
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/without-languages.rb
==> Name

View File

@ -3,7 +3,7 @@ describe Cask::Cmd::InternalStanza, :cask do
command = described_class.new("homepage", "local-caffeine")
expect {
command.run
}.to output("https://example.com/local-caffeine\n").to_stdout
}.to output("https://example.com\n").to_stdout
end
it "raises an exception when stanza is unknown/unsupported" do

View File

@ -3,7 +3,7 @@ cask 'bad-checksum' do
sha256 'badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'installer-with-uninstall' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
installer manual: 'Caffeine.app'

View File

@ -3,7 +3,7 @@ cask => 'invalid-header-format' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'invalid-header-token-mismatch-this-text-does-not-belong' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'invalid-header-version' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'invalid-two-homepage' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
homepage 'https://www.example.com/local-caffeine'
app 'Caffeine.app'

View File

@ -4,7 +4,7 @@ cask 'invalid-two-url' do
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
url 'https://example.com/caffeine.zip'
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -4,7 +4,7 @@ cask 'invalid-two-version' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'local-caffeine' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -4,7 +4,7 @@ cask 'local-transmission' do
sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68'
url "file://#{TEST_FIXTURE_DIR}/cask/transmission-2.61.dmg"
homepage 'https://example.com/local-transmission'
homepage 'https://example.com'
app 'Transmission.app'
end

View File

@ -2,7 +2,7 @@ cask 'missing-checksum' do
version '1.2.3'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'no-checksum' do
sha256 :no_check
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'bad-checksum' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'local-caffeine' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'local-transmission' do
sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68'
url "file://#{TEST_FIXTURE_DIR}/cask/transmission-2.61.dmg"
homepage 'https://example.com/local-transmission'
homepage 'https://example.com'
app 'Transmission.app'
end

View File

@ -3,7 +3,7 @@ cask 'version-latest' do
sha256 :no_check
url "file://#{TEST_FIXTURE_DIR}/cask/caffeines.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine Mini.app'
app 'Caffeine Pro.app'

View File

@ -3,7 +3,7 @@ cask 'version-latest' do
sha256 :no_check
url "file://#{TEST_FIXTURE_DIR}/cask/caffeines.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine Mini.app'
app 'Caffeine Pro.app'

View File

@ -3,7 +3,7 @@ cask 'will-fail-if-upgraded' do
sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68'
url "file://#{TEST_FIXTURE_DIR}/cask/transmission-2.61.dmg"
homepage 'https://example.com/local-transmission'
homepage 'https://example.com'
app 'container'
end

View File

@ -3,7 +3,7 @@ cask 'with-alt-target' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app', target: 'AnotherName.app'
end

View File

@ -3,7 +3,7 @@ cask 'with-caveats' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'

View File

@ -3,7 +3,7 @@ cask 'with-conditional-caveats' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'

View File

@ -3,7 +3,7 @@ cask 'with-installer-manual' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
installer manual: 'Caffeine.app'
end

View File

@ -12,7 +12,7 @@ cask 'with-languages' do
end
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -3,7 +3,7 @@ cask 'with-two-apps-correct' do
sha256 '3178fbfd1ea5d87a2a0662a4eb599ebc9a03888e73f37538d9f3f6ee69d2368e'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeines.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine Mini.app'
app 'Caffeine Pro.app'

View File

@ -3,7 +3,7 @@ cask 'with-two-apps-subdir' do
sha256 'd687c22a21c02bd8f07da9302c8292b93a04df9a929e3f04d09aea6c76f75c65'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeines-subdir.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeines/Caffeine Mini.app'
app 'Caffeines/Caffeine Pro.app'

View File

@ -3,7 +3,7 @@ cask 'without-languages' do
sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'https://example.com/local-caffeine'
homepage 'https://example.com'
app 'Caffeine.app'
end

View File

@ -92,6 +92,11 @@ def curl_check_http_content(url, user_agents: [:default], check_content: false,
return "The URL #{url} is not reachable (HTTP status code #{details[:status]})"
end
if url.start_with?("https://") && ENV["HOMEBREW_NO_INSECURE_REDIRECT"] &&
!details[:final_url].start_with?("https://")
return "The URL #{url} redirects back to HTTP"
end
return unless hash_needed
secure_url = url.sub "http", "https"
@ -110,7 +115,9 @@ def curl_check_http_content(url, user_agents: [:default], check_content: false,
details[:content_length] == secure_details[:content_length]
file_match = details[:file_hash] == secure_details[:file_hash]
if etag_match || content_length_match || file_match
if (etag_match || content_length_match || file_match) &&
secure_details[:final_url].start_with?("https://") &&
url.start_with?("http://")
return "The URL #{url} should use HTTPS rather than HTTP"
end
@ -121,7 +128,9 @@ def curl_check_http_content(url, user_agents: [:default], check_content: false,
secure_details[:file] = secure_details[:file].gsub(no_protocol_file_contents, "/")
# Check for the same content after removing all protocols
if details[:file] == secure_details[:file]
if (details[:file] == secure_details[:file]) &&
secure_details[:final_url].start_with?("https://") &&
url.start_with?("http://")
return "The URL #{url} should use HTTPS rather than HTTP"
end
@ -150,11 +159,16 @@ def curl_http_content_headers_and_checksum(url, hash_needed: false, user_agent:
while status_code == :unknown || status_code.to_s.start_with?("3")
headers, _, output = output.partition("\r\n\r\n")
status_code = headers[%r{HTTP\/.* (\d+)}, 1]
final_url = headers[/^Location:\s*(.*)$/i, 1]&.chomp
end
output_hash = Digest::SHA256.digest(output) if hash_needed
final_url ||= url
{
url: url,
final_url: final_url,
status: status_code,
etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2],
content_length: headers[/Content-Length: (\d+)/, 1],