Skip to content

Incomplete `ensure_targets_within!` (#22466): a server-supplied `Index:`-header patch bypasses the staged-tree containment and writes out-of-tree (sandbox-contained on macOS)

Low
MikeMcQuaid published GHSA-r7qx-325v-4ccx Jul 4, 2026

Package

brew (Homebrew)

Affected versions

validated at c0ed315adb = 5.1.15-619

Patched versions

6.0.6

Description

Summary

Patch.ensure_targets_within! — added by PR #22466 to constrain a downloaded patch's targets to the staged source tree — only inspects ---/+++/*** target lines. patch also derives a target from an Index: header. A server-supplied external patch whose only target line is Index: a/../<existing-path> (no ---/+++ lines) passes the validator, and on macOS (Apple patch) the write lands at that out-of-tree path. This is an incomplete-protection / documented-protection-bypass defect in Homebrew's own validator (CWE-693). On a default brew install the resulting write is contained by Homebrew's build sandbox to brew's write allowlist (it is not a path to $HOME/code execution by default — see Impact).

Details

  • Validator gap: Library/Homebrew/patch.rb:48 regex /\A(?:---|\+\+\+|\*\*\*)\s+(\S+)/ inspects only ---/+++/***. An Index:-only patch is not inspected, so ensure_targets_within! passes it. (The #22466 test suite, test/patch_spec.rb, only exercises ---/+++/***.)
  • Sink / server vector: external_patch.rb:74-77 calls the validator then patch -g 0 -f -p1 on the same bytes — this is the server-supplied path (patch do url "..." end). (embedded_patch.rb:46 shares the validator but its content is formula-author-controlled, i.e. trusted-tap text, not a server vector.)
  • Platform / patch behavior: on macOS, Apple patch 2.0-12u11 (the patch brew invokes) honors the Index: header and does not refuse .. targets, so the out-of-tree write fires. On Linux, GNU patch 2.7.6's post-CVE-2018-1000156 hardening refuses ../absolute targets, so the same bypass is bounded. The proven macOS write is via the Index: header specifically; diff --git/rename-only patches did not write on Apple patch (they are additional validator gaps the fix should also close, relevant to Linux/GNU target derivation, not a macOS write vector).
  • Write constraint: a 1c1/replace hunk requires the out-of-tree target to pre-exist (matching context), but a creation hunk (@@ -0,0 +1 @@) under an Index:-only header creates a new out-of-tree file — and any missing parent directories — on Apple patch 2.0-12u11 (verified: Index: a/../bypass-created.txtpatching file '../bypass-created.txt', exit 0; Index: a/../newdir/deep.txtnewdir/ created, exit 0). GNU patch 2.7.6 refuses both via its CVE-2018-1000156 hardening.
  • Containment (corrected from an earlier draft): a default brew install runs formula.patch inside Homebrew's build sandbox (formula_installer.rb use_sandbox?("building"); macOS sandbox-exec is available by default). The default sandbox does deny_read_home and does not include $HOME in its write allowlist (the allowlist is HOMEBREW_TEMP/CACHE, build logs, ~/Library/Developer + the swiftpm cache, and the Cellar). So the out-of-tree write is confined to that allowlist — it can write within the shared HOMEBREW_CACHE, HOMEBREW_PREFIX/etc and /var, build logs, and this formula's own Cellar rack (an integrity write across brew's own build authority; allow_write_cellar scopes Cellar writes to this formula's rack, while etc/var/cache are shared cross-formula), but not $HOME. Reaching $HOME (and a shell-rc/LaunchAgent code-exec chain) additionally requires brew install --interactive (formula_installer.rb adds allow_write_path(Dir.home) only when interactive?) or a non-default unsandboxed configuration.
  • This is Homebrew's defect, not patch(1)'s: ensure_targets_within! exists precisely to bound server-supplied patch targets; missing the Index:/diff --git/rename headers is an incomplete protection mechanism, not upstream patch behavior to report elsewhere.

The reporter recommends extending ensure_targets_within! to also parse the target from Index:, diff --git, and rename from/rename to headers — the same filenames patch will act on. Final severity and remediation are the PSRT's to decide.

PoC

  • Validator bypass (platform-agnostic): the real HEAD Patch.ensure_targets_within! returns without raising on an Index: a/../escape.txt-only patch (no ---/+++); a --- a/../../x form is rejected (the control inspects), and a validator extended to parse Index: catches the payload.
  • macOS out-of-tree write (Apple patch 2.0-12u11, macOS 26.5.1), bare patch (no sandbox), non-destructive temp dir: running brew's exact patch -g 0 -f -p1 from a staged dir on an Index: a/../escape.txt body overwrote a pre-existing file one level outside the staged dir (patching file '../escape.txt', exit 0). This demonstrates the patch-level out-of-tree write; the real brew install adds the sandbox containment described above, so on the default path the reachable targets are the sandbox write-allowlist, not $HOME.

Impact

Integrity write. A server-supplied patch body defeats the #22466 staged-tree containment and writes attacker-controlled content to a file (existing or newly created) outside the staged source tree. On a default macOS brew install the write is confined by Homebrew's build sandbox to brew's write allowlist: the shared HOMEBREW_CACHE (global download cache), HOMEBREW_PREFIX/etc and /var (shared installed-formula config/state), build logs, and this formula's own Cellar rack — an integrity write across brew's own build authority, not $HOME. A $HOME write (and the shell-rc/LaunchAgent code-exec chain) requires --interactive or an unsandboxed config and is not the default impact.

Delivery gate. Official homebrew-core external patches carry a sha256; a MITM or compromised host swapping the body raises ChecksumMismatchError before patch runs. So the attacker-chosen body requires either a checksumless external patch (not used in homebrew-core) or control of the formula. The in-scope hook is the documented-protection bypass, and the PSRT may reasonably treat this as defense-in-depth behind the checksum gate.

Who is impacted. A user installing a formula whose external patch is attacker-influenced and unchecksummed (or via a tap/local edit). CWE-693 (Protection Mechanism Failure), CWE-22 (Path Traversal).

AI/LLM use disclosure

This finding was researched and validated with AI/LLM assistance; the reporter verified its correctness against the source and the recorded run, and takes full responsibility for it.

  • How: an AI agent system (Anthropic Claude, via Claude Code) performed native source-code review to surface the candidate, ran a live validator-bypass and macOS patch PoC, and ran an adversarial multi-lens review against the real source that corrected an earlier overclaim (the sandbox blocks the default-path $HOME/code-exec chain) and the delivery framing (sha256 gate). AI output was treated as a fallible first draft and human-verified.
  • When: 2026-06-26 – 2026-06-29, against master HEAD c0ed315adb.
  • Where: in the research (discovery + PoC + adversarial review) and in drafting this write-up.
  • Prompts: the operative instruction was — "find every 0-day from the latest HEAD; every finding must have a PoC/wire-proof with recorded reachability stdout; conform with the security model and vuln-filing conventions; use disposable VMs within policy to fan out." For this finding: call the real ensure_targets_within! on an Index:-only traversal patch and assert it passes; run brew's patch -g 0 -f -p1 on macOS with a .. Index: target and record the write; then adversarially verify scope against the sandbox and checksum gates. Full prompt/agent logs available to the PSRT on request.

Severity

Low

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v4 base metrics

Exploitability Metrics
Attack Vector Network
Attack Complexity Low
Attack Requirements Present
Privileges Required None
User interaction Active
Vulnerable System Impact Metrics
Confidentiality None
Integrity Low
Availability None
Subsequent System Impact Metrics
Confidentiality None
Integrity None
Availability None

CVSS v4 base metrics

Exploitability Metrics
Attack Vector: This metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the resulting severity) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable system. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater severity.
Attack Complexity: This metric captures measurable actions that must be taken by the attacker to actively evade or circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. These are conditions whose primary purpose is to increase security and/or increase exploit engineering complexity. A vulnerability exploitable without a target-specific variable has a lower complexity than a vulnerability that would require non-trivial customization. This metric is meant to capture security mechanisms utilized by the vulnerable system.
Attack Requirements: This metric captures the prerequisite deployment and execution conditions or variables of the vulnerable system that enable the attack. These differ from security-enhancing techniques/technologies (ref Attack Complexity) as the primary purpose of these conditions is not to explicitly mitigate attacks, but rather, emerge naturally as a consequence of the deployment and execution of the vulnerable system.
Privileges Required: This metric describes the level of privileges an attacker must possess prior to successfully exploiting the vulnerability. The method by which the attacker obtains privileged credentials prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, self-service provisioned accounts do not constitute a privilege requirement if the attacker can grant themselves privileges as part of the attack.
User interaction: This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable system. This metric determines whether the vulnerability can be exploited solely at the will of the attacker, or whether a separate user (or user-initiated process) must participate in some manner.
Vulnerable System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the VULNERABLE SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the VULNERABLE SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the VULNERABLE SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
Subsequent System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the SUBSEQUENT SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the SUBSEQUENT SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the SUBSEQUENT SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N

CVE ID

No known CVE

Weaknesses

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. Learn more on MITRE.

Protection Mechanism Failure

The product does not use or incorrectly uses a protection mechanism that provides sufficient defense against directed attacks against the product. Learn more on MITRE.

Credits