Restrict direct url installs to the file:// scheme
This commit is contained in:
parent
ab7e49c462
commit
8b0a4a98bf
@ -12,6 +12,9 @@ module Cask
|
||||
module CaskLoader
|
||||
extend Context
|
||||
|
||||
ALLOWED_URL_SCHEMES = %w[file].freeze
|
||||
private_constant :ALLOWED_URL_SCHEMES
|
||||
|
||||
module ILoader
|
||||
extend T::Helpers
|
||||
interface!
|
||||
@ -171,17 +174,25 @@ module Cask
|
||||
new(uri)
|
||||
end
|
||||
|
||||
attr_reader :url
|
||||
attr_reader :url, :name
|
||||
|
||||
sig { params(url: T.any(URI::Generic, String)).void }
|
||||
def initialize(url)
|
||||
@url = URI(url)
|
||||
super Cache.path/File.basename(T.must(@url.path))
|
||||
@name = File.basename(T.must(@url.path))
|
||||
super Cache.path/name
|
||||
end
|
||||
|
||||
def load(config:)
|
||||
path.dirname.mkpath
|
||||
|
||||
if ALLOWED_URL_SCHEMES.exclude?(url.scheme)
|
||||
raise UnsupportedInstallationMethod,
|
||||
"Non-checksummed download of #{name} formula file from an arbitrary URL is unsupported! " \
|
||||
"`brew extract` or `brew create` and `brew tap-new` to create a formula file in a tap " \
|
||||
"on GitHub instead."
|
||||
end
|
||||
|
||||
begin
|
||||
ohai "Downloading #{url}"
|
||||
::Utils::Curl.curl_download url, to: path
|
||||
|
||||
@ -17,8 +17,8 @@ module Formulary
|
||||
extend Context
|
||||
extend Cachable
|
||||
|
||||
URL_START_REGEX = %r{(https?|ftp|file)://}
|
||||
private_constant :URL_START_REGEX
|
||||
ALLOWED_URL_SCHEMES = %w[file].freeze
|
||||
private_constant :ALLOWED_URL_SCHEMES
|
||||
|
||||
# `:codesign` and custom requirement classes are not supported.
|
||||
API_SUPPORTED_REQUIREMENTS = [:arch, :linux, :macos, :maximum_macos, :xcode].freeze
|
||||
@ -696,7 +696,7 @@ module Formulary
|
||||
def self.try_new(ref, from: T.unsafe(nil), warn: false)
|
||||
ref = ref.to_s
|
||||
|
||||
new(ref, from:) if URL_START_REGEX.match?(ref)
|
||||
new(ref, from:) if URI(ref).scheme.present?
|
||||
end
|
||||
|
||||
attr_reader :url
|
||||
@ -713,12 +713,8 @@ module Formulary
|
||||
end
|
||||
|
||||
def load_file(flags:, ignore_errors:)
|
||||
match = url.match(%r{githubusercontent.com/[\w-]+/[\w-]+/[a-f0-9]{40}(?:/Formula)?/(?<name>[\w+-.@]+).rb})
|
||||
if match
|
||||
raise UnsupportedInstallationMethod,
|
||||
"Installation of #{match[:name]} from a GitHub commit URL is unsupported! " \
|
||||
"`brew extract #{match[:name]}` to a stable tap on GitHub instead."
|
||||
elsif url.match?(%r{^(https?|ftp)://})
|
||||
url_scheme = URI(url).scheme
|
||||
if ALLOWED_URL_SCHEMES.exclude?(url_scheme)
|
||||
raise UnsupportedInstallationMethod,
|
||||
"Non-checksummed download of #{name} formula file from an arbitrary URL is unsupported! " \
|
||||
"`brew extract` or `brew create` and `brew tap-new` to create a formula file in a tap " \
|
||||
|
||||
@ -18,4 +18,34 @@ RSpec.describe Cask::CaskLoader::FromURILoader do
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
describe "::load" do
|
||||
it "raises an error when given an https URL" do
|
||||
loader = described_class.new("https://brew.sh/foo.rb")
|
||||
expect do
|
||||
loader.load(config: nil)
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "raises an error when given an ftp URL" do
|
||||
loader = described_class.new("ftp://brew.sh/foo.rb")
|
||||
expect do
|
||||
loader.load(config: nil)
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "raises an error when given an sftp URL" do
|
||||
loader = described_class.new("sftp://brew.sh/foo.rb")
|
||||
expect do
|
||||
loader.load(config: nil)
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "does not raise an error when given a file URL" do
|
||||
loader = described_class.new("file://#{TEST_FIXTURE_DIR}/cask/Casks/local-caffeine.rb")
|
||||
expect do
|
||||
loader.load(config: nil)
|
||||
end.not_to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -523,6 +523,38 @@ RSpec.describe Formulary do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when passed a URL" do
|
||||
it "raises an error when given an https URL" do
|
||||
expect do
|
||||
described_class.factory("https://brew.sh/foo.rb")
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "raises an error when given a bottle URL" do
|
||||
expect do
|
||||
described_class.factory("https://brew.sh/foo-1.0.arm64_catalina.bottle.tar.gz")
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "raises an error when given an ftp URL" do
|
||||
expect do
|
||||
described_class.factory("ftp://brew.sh/foo.rb")
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "raises an error when given an sftp URL" do
|
||||
expect do
|
||||
described_class.factory("sftp://brew.sh/foo.rb")
|
||||
end.to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
|
||||
it "does not raise an error when given a file URL" do
|
||||
expect do
|
||||
described_class.factory("file://#{TEST_FIXTURE_DIR}/testball.rb")
|
||||
end.not_to raise_error(UnsupportedInstallationMethod)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
specify "::from_contents" do
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user