Filter sensitive environment variables during Ruby evals#22384
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR tightens security during evaluation of untrusted Ruby code by temporarily removing “token-like” environment variables while formulae, casks, and external Ruby commands are eval’d/require’d, then restoring the original environment afterward so normal command execution still sees the caller’s environment.
Changes:
- Extend
ENV.clear_sensitive_environment!to support a block form that restores the environment after yielding. - Wrap formula and cask evaluation (
module_eval/instance_eval) inENV.clear_sensitive_environment!to prevent top-level DSL code from reading sensitive variables. - Wrap external Ruby command loading (
Homebrew.require?) in the same environment-scrubbing block and add test coverage for formula, cask, andbrew helppaths.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| Library/Homebrew/extend/ENV.rb | Adds block form to clear_sensitive_environment! with ensure-based restoration. |
| Library/Homebrew/formulary.rb | Scrubs sensitive env vars during formula module_eval loading. |
| Library/Homebrew/cask/cask_loader.rb | Scrubs sensitive env vars during cask instance_eval loading (content + path loaders). |
| Library/Homebrew/commands.rb | Scrubs sensitive env vars while require-loading external Ruby v2 commands. |
| Library/Homebrew/cli/parser.rb | Scrubs sensitive env vars while require-loading command parsers from Ruby command files. |
| Library/Homebrew/test/ENV_spec.rb | Adds spec verifying env restoration and non-persistence of block mutations. |
| Library/Homebrew/test/formulary_spec.rb | Adds spec ensuring formula top-level code can’t see sensitive env vars and env is restored. |
| Library/Homebrew/test/cask/cask_loader_spec.rb | Adds spec ensuring cask DSL evaluation can’t see sensitive env vars and env is restored. |
| Library/Homebrew/test/cmd/help_spec.rb | Adds integration coverage ensuring external command require doesn’t leak sensitive env vars. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
50499ce to
5f59f92
Compare
issyl0
approved these changes
May 22, 2026
- Hide token-like environment variables while formulae and casks are evaluated so top-level DSL code cannot read them. - Restore the caller environment after metadata loading and command parser requires so command execution keeps its normal environment. - Keep the filtering extension lightweight so command parser loading does not require slow startup dependencies. - Use `requires_ancestor` for the ENV module typing rather than `T.unsafe(self)`. - Cover formula, cask and external command require paths.
5f59f92 to
0dc0566
Compare
3 tasks
caarlos0
added a commit
to goreleaser/goreleaser
that referenced
this pull request
May 29, 2026
Fixes #6638. ## Problem Homebrew 5.1.14 ([Homebrew/brew#22384](Homebrew/brew#22384)) scrubs sensitive environment variables (including `HOMEBREW_GITHUB_API_TOKEN`) for the duration of cask `instance_eval`. The previously documented `homebrew_casks` private-repo example interpolates `#{GitHubHelper.token}` directly inside `url.template` and `url.headers`, both of which are evaluated at cask-load time — exactly when the token is hidden. Every `brew install`/`update`/`upgrade` against an affected tap fails with: > Error: Failed to retrieve github api token ## Fix Docs-only — replace the snippet with a `CurlDownloadStrategy` subclass referenced via `url.using:`. `using:` takes a **class reference**, so cask-load only captures the constant; Homebrew restores the environment before instantiating the strategy and calling `fetch`, so the token lookup happens at download time and works again. Also added a `[!WARNING]` callout explaining the 5.1.14 regression so users hitting the error in the wild land on this section via search. ## Notes - No Go changes — `url.template`, `url.using`, `url.verified`, `url.headers` already exist on `HomebrewCaskURL` and render correctly via `internal/pipe/cask/templates/additional_url_params.rb`. - Existing Go tests that use the old Ruby snippet as a `custom_block` fixture were left as-is — they exercise Go template rendering, not actual brew behavior, so they're still valid. - The "optional enhancement" of auto-generating the download strategy from a flag is intentionally out of scope (per maintainer comment on the issue: private repos use varied URL templates, so this shouldn't be baked in. EOF ) Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This provides a potential security improvement for untrusted Ruby code but has minimal enough overhead that we can just do it always. We may add an opt-out for this behaviour if it breaks things for people but it was already applied during install/test/postinstall blocks.
brew lgtm(style, typechecking and tests) with your changes locally?OpenAI Codex 5.5 xhigh with local review and testing.