From b30d13c3efdd9e1a7164e8a7fdf922b0c2f966bf Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Mon, 18 Aug 2025 03:38:49 +0100 Subject: [PATCH 1/2] formulary: do not allow using the cache if explicitly forbidding paths --- Library/Homebrew/formulary.rb | 10 ++++++-- Library/Homebrew/test/formulary_spec.rb | 32 +++++++++++++++++-------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 8135629707..ad97588aa8 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -619,9 +619,15 @@ module Formulary if Homebrew::EnvConfig.forbid_packages_from_paths? path_realpath = path.realpath.to_s path_string = path.to_s + allowed_paths = ["#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/"] + + # Do not allow the cache if we explicitly set HOMEBREW_FORBID_PACKAGES_FROM_PATHS + # as the cache can contain arbitrary downloads. Allow it otherwise for convenience. + allowed_paths << "#{HOMEBREW_CACHE}/" unless ENV["HOMEBREW_FORBID_PACKAGES_FROM_PATHS"].present? + if (path_realpath.end_with?(".rb") || path_string.end_with?(".rb")) && - !path_realpath.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/", "#{HOMEBREW_CACHE}/") && - !path_string.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/", "#{HOMEBREW_CACHE}/") + !path_realpath.start_with?(*allowed_paths) && + !path_string.start_with?(*allowed_paths) if path_string.include?("./") || path_string.end_with?(".rb") || path_string.count("/") != 2 raise <<~WARNING Homebrew requires formulae to be in a tap, rejecting: diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index 3ab0bafb71..c489fb342d 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -141,19 +141,31 @@ RSpec.describe Formulary do end.to raise_error(FormulaUnavailableError) end - it "allows cache paths even when paths are disabled" do - ENV["HOMEBREW_FORBID_PACKAGES_FROM_PATHS"] = "1" - cache_dir = HOMEBREW_CACHE/"test_formula_cache" - cache_dir.mkpath - cache_formula_path = cache_dir/formula_path.basename - FileUtils.cp formula_path, cache_formula_path - begin - formula = described_class.factory(cache_formula_path) - expect(formula).to be_a(Formula) - ensure + context "when given a cache path" do + let(:cache_dir) { HOMEBREW_CACHE/"test_formula_cache" } + let(:cache_formula_path) { cache_dir/formula_path.basename } + + before do + cache_dir.mkpath + FileUtils.cp formula_path, cache_formula_path + end + + after do cache_formula_path.unlink if cache_formula_path.exist? cache_dir.rmdir if cache_dir.exist? end + + it "allows cache paths when paths are implicitly disabled" do + allow(Homebrew::EnvConfig).to receive(:forbid_packages_from_paths?).and_return(true) + expect(described_class.factory(cache_formula_path)).to be_a(Formula) + end + + it "disallows cache paths when paths are explicitly disabled" do + ENV["HOMEBREW_FORBID_PACKAGES_FROM_PATHS"] = "1" + expect do + described_class.factory(cache_formula_path) + end.to raise_error(/requires formulae to be in a tap/) + end end context "when given a bottle" do From b1b28fb2f461aef2b4b2d481fa4670a9b6ea9594 Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Mon, 18 Aug 2025 15:24:02 +0100 Subject: [PATCH 2/2] formulary: forbid cache paths --- Library/Homebrew/formulary.rb | 10 ++-------- Library/Homebrew/test/formulary_spec.rb | 5 ----- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index ad97588aa8..52728158a5 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -619,15 +619,9 @@ module Formulary if Homebrew::EnvConfig.forbid_packages_from_paths? path_realpath = path.realpath.to_s path_string = path.to_s - allowed_paths = ["#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/"] - - # Do not allow the cache if we explicitly set HOMEBREW_FORBID_PACKAGES_FROM_PATHS - # as the cache can contain arbitrary downloads. Allow it otherwise for convenience. - allowed_paths << "#{HOMEBREW_CACHE}/" unless ENV["HOMEBREW_FORBID_PACKAGES_FROM_PATHS"].present? - if (path_realpath.end_with?(".rb") || path_string.end_with?(".rb")) && - !path_realpath.start_with?(*allowed_paths) && - !path_string.start_with?(*allowed_paths) + !path_realpath.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/") && + !path_string.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/") if path_string.include?("./") || path_string.end_with?(".rb") || path_string.count("/") != 2 raise <<~WARNING Homebrew requires formulae to be in a tap, rejecting: diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index c489fb342d..0f957e23e4 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -155,11 +155,6 @@ RSpec.describe Formulary do cache_dir.rmdir if cache_dir.exist? end - it "allows cache paths when paths are implicitly disabled" do - allow(Homebrew::EnvConfig).to receive(:forbid_packages_from_paths?).and_return(true) - expect(described_class.factory(cache_formula_path)).to be_a(Formula) - end - it "disallows cache paths when paths are explicitly disabled" do ENV["HOMEBREW_FORBID_PACKAGES_FROM_PATHS"] = "1" expect do