diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index 0cbd7db525e55..2a78e2f5cbe67 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -37,6 +37,7 @@ def add_rule(allow:, operation:, filter: nil, modifier: nil) def allow_write(path:, type: :literal) add_rule allow: true, operation: "file-write*", filter: path_filter(path, type) add_rule allow: true, operation: "file-write-setugid", filter: path_filter(path, type) + add_rule allow: true, operation: "file-write-mode", filter: path_filter(path, type) end sig { params(path: T.any(String, Pathname), type: Symbol).void } @@ -289,6 +290,8 @@ class SandboxProfile (regex #"^/dev/tty[a-z0-9]*$") ) (deny file-write*) ; deny non-allowlist file write operations + (deny file-write-setugid) ; deny non-allowlist file write SUID/SGID operations + (deny file-write-mode) ; deny non-allowlist file write mode operations (allow process-exec (literal "/bin/ps") (with no-sandbox) diff --git a/Library/Homebrew/test/sandbox_spec.rb b/Library/Homebrew/test/sandbox_spec.rb index 79845beaa2718..f0954877af393 100644 --- a/Library/Homebrew/test/sandbox_spec.rb +++ b/Library/Homebrew/test/sandbox_spec.rb @@ -57,4 +57,32 @@ .and output(a_string_matching(/foo/).and(matching(/bar/).and(not_matching(/Python/)))).to_stdout end end + + describe "#disallow chmod on some directory" do + it "formula does a chmod to opt" do + expect { sandbox.exec "chmod", "ug-w", HOMEBREW_PREFIX }.to raise_error(ErrorDuringExecution) + end + + it "allows chmod on a path allowed to write" do + mktmpdir do |path| + FileUtils.touch path/"foo" + sandbox.allow_write_path(path) + expect { sandbox.exec "chmod", "ug-w", path/"foo" }.not_to raise_error(ErrorDuringExecution) + end + end + end + + describe "#disallow chmod SUID or SGID on some directory" do + it "formula does a chmod 4000 to opt" do + expect { sandbox.exec "chmod", "4000", HOMEBREW_PREFIX }.to raise_error(ErrorDuringExecution) + end + + it "allows chmod 4000 on a path allowed to write" do + mktmpdir do |path| + FileUtils.touch path/"foo" + sandbox.allow_write_path(path) + expect { sandbox.exec "chmod", "4000", path/"foo" }.not_to raise_error(ErrorDuringExecution) + end + end + end end