Skip to content

feat(external_commands): wire ExternalCommands env filtering into run() - #1278

Open
smoparth wants to merge 1 commit into
python-wheel-build:mainfrom
smoparth:feat/wire-env-filter
Open

feat(external_commands): wire ExternalCommands env filtering into run()#1278
smoparth wants to merge 1 commit into
python-wheel-build:mainfrom
smoparth:feat/wire-env-filter

Conversation

@smoparth

@smoparth smoparth commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Add env_filter parameter to external_commands.run() and thread it through all call sites that execute untrusted third-party code (PEP 517 build hooks, wheel metadata) and uv cache invalidation.

os.environ is filtered through ExternalCommands.filter_env() before extra_environ is applied, ensuring injected build variables are never stripped.

Closes: #1083

Pull Request Description

What

Why

…run()`

Add `env_filter` parameter to `external_commands.run()` and thread it
through all call sites that execute untrusted third-party code (PEP 517
build hooks, wheel metadata) and  uv cache invalidation.

`os.environ` is filtered through `ExternalCommands.filter_env()` before
`extra_environ` is applied, ensuring injected build variables are never
stripped.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Shanmukh Pawan <smoparth@redhat.com>
@smoparth
smoparth requested a review from a team as a code owner July 27, 2026 19:30
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

external_commands.run() now optionally filters os.environ before applying extra_environ. The configured filter is passed through build environment creation and command execution, cache cleanup, backend hook calls, and wheel repacking. Unit tests cover default behavior, wildcard and selective deletions, and preservation of explicitly injected variables.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly describes the main change: adding ExternalCommands env filtering to run().
Description check ✅ Passed The description matches the code changes and explains the new env_filter behavior and call sites.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mergify mergify Bot added the ci label Jul 27, 2026
@LalatenduMohanty

Copy link
Copy Markdown
Member

@smoparth Please mention Closes: #1083 in the PR description.

@smoparth

smoparth commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Wiring decisions

Wired (5 call sites) for untrusted third-party code

These call sites execute PEP 517 build-backend hooks or other third-party scripts, so they receive env_filter=ctx.settings.external_commands:

Call site File Why
BuildEnvironment.run() build_environment.py Runs PEP 517 hooks inside the build venv
BuildEnvironment._createenv() build_environment.py Creates the build venv via uv
_run_hook_with_extra_environ() dependencies.py Invokes build-backend hooks (get_requires, etc.)
_add_extra_metadata() wheels.py Runs wheel pack on built wheels
WorkContext.uv_clean_cache() context.py Invalidates uv cache entries

Not wired (8 call sites) — trusted tools only

These call sites invoke our own trusted tools (git, cargo, patch) and do not run arbitrary third-party code. They have no access to a ctx object today, so wiring them would require plumbing ctx (or the ExternalCommands instance) through the entire call chain.

Call site File Commands invoked
clone_source() (×3) gitutils.py git clone, git checkout
clone_source_ref() (×2) gitutils.py git checkout, git submodule
git_clean() gitutils.py git clean
vendor_rust() vendor_rust.py cargo vendor
_apply_patch() sources.py patch -p1

To achieve full filtering

If all subprocesses should be filtered including git, cargo, and patch — the ctx (or ExternalCommands instance) would need to be threaded through the following call chains:

  • sources.py_apply_patch(), called from _apply_patches() -- which already receives ctx; straightforward one-hop plumb.
  • gitutils.pyclone_source() / clone_source_ref() / git_clean() -- these are standalone utility functions. ctx would need to be added as a parameter, and all callers in sources.py and bootstrapper/ need to be updated.
  • vendor_rust.pyvendor_rust(), called from _prepare_source.py -- ctx is available one level up but not passed into vendor_rust() today.

@LalatenduMohanty

Copy link
Copy Markdown
Member

Overall direction of the PR looks good to me.

@LalatenduMohanty
LalatenduMohanty requested a review from tiran July 27, 2026 19:38
@tiran

tiran commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

This approach defaults to insecure behavior. In #1171 I proposed to deprecate and eventually remove external_commands.run in favor of WorkContext.run_* and BuildEnvironment.run_sandboxed methods.

@smoparth

Copy link
Copy Markdown
Contributor Author

This approach defaults to insecure behavior. In #1171 I proposed to deprecate and eventually remove external_commands.run in favor of WorkContext.run_* and BuildEnvironment.run_sandboxed methods.

Thanks for pointing to #1171, I missed that follow-up proposal. I've been going with the filter-env proposal#api-changes and actually even worked on the data model of it earlier, but had a few questions I wanted to clarify before pushing code. By the time I got back to it, I saw you'd already pushed that part and now again I missed this context about the follow-up proposal.

Defaulting to secure behavior makes a lot of sense. I'm eager to work on Fromager, I think we should have an epic or an issue with linked sub-tasks to help with getting the correct context and picking up next steps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add environment variable filtering for external commands

3 participants