From 9e05a54e679086460972ecf0c9bb755658ec03b4 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Sat, 24 Oct 2026 17:28:47 +0100 Subject: [PATCH] Allow reading private sandbox temporary files - Let archive tools read files in the sandbox's temporary directory without granting read access to its parent. - Exercise temporary-file reads and denied parent access in the sandbox. Fixes #24348 --- Library/Homebrew/sandbox.rb | 1 + Library/Homebrew/test/sandbox_shared_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index 7f35f724257d9..2c0c308eceff2 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -902,6 +902,7 @@ def home_write_paths = [] sig { params(tmpdir: String).returns(T::Hash[String, String]) } def sandbox_environment(tmpdir) + allow_read path: tmpdir, type: :subpath allow_write_path(tmpdir) allow_network path: tmpdir, type: :subpath { "HOMEBREW_TEMP" => tmpdir, "TMPDIR" => tmpdir, "TEMP" => tmpdir, "TMP" => tmpdir } diff --git a/Library/Homebrew/test/sandbox_shared_spec.rb b/Library/Homebrew/test/sandbox_shared_spec.rb index 30ac240c92764..ba2b1bb82cf2a 100644 --- a/Library/Homebrew/test/sandbox_shared_spec.rb +++ b/Library/Homebrew/test/sandbox_shared_spec.rb @@ -269,6 +269,26 @@ allow(described_class).to receive(:isolate_operation?).and_call_original end + it "allows reading only its private temporary directory under a denied parent" do + temporary_directory = mktmpdir + outside = temporary_directory/"outside" + outside.write("secret") + sandbox.deny_read_path temporary_directory + result = sandbox.capture(RbConfig.ruby, temporary_directory:, args: ["-e", <<~RUBY, outside]) + file = File.join(ENV.fetch("TMPDIR"), "archive") + File.write(file, "contents") + puts File.read(file) + begin + File.read(ARGV.fetch(0)) + abort "Read escaped the sandbox" + rescue Errno::EPERM, Errno::EACCES + nil + end + RUBY + + expect(result.stdout).to eq("contents\n") + end + it "allows its output directory and denies writes through an escaping symlink" do directory = mktmpdir output = directory/"output"