diff --git a/docs/proposals/filter-env.md b/docs/proposals/filter-env.md new file mode 100644 index 00000000..6cd459c1 --- /dev/null +++ b/docs/proposals/filter-env.md @@ -0,0 +1,120 @@ +# Filter environment variables + +- Author: Christian Heimes +- Created: 2026-04-23 +- Status: Open +- Issue: [#1083](https://github.com/python-wheel-build/fromager/issues/1083) + +## What + +A configurable filter for environment variables inherited by external +commands. Fromager strips sensitive variables from `os.environ` before +they reach build scripts, hooks, or other subprocesses. + +## Why + +Fromager runs arbitrary third-party code during builds -- PEP 517 hooks, +setup scripts, patching commands, git operations. Every subprocess +today inherits the full parent environment, including credentials, +CI tokens, and registry passwords that have no business inside a build. + +This is a supply-chain risk. A compromised or careless build script can +read and exfiltrate any variable it inherits. The risk is higher in CI +environments where runners routinely carry cloud credentials, API tokens, +and service account keys. + +Controlling which variables pass through also improves reproducibility. +Stray environment can silently alter build behavior (compiler flags, +proxy settings, locale overrides). Filtering makes builds more +deterministic. + +`sudo` solves the same problem with `env_keep` and `env_delete` in +sudoers. This proposal follows that proven model. + +References: + +- [sudo env_keep / env_delete](https://www.sudo.ws/docs/man/sudoers.man/#Command_environment) + +## Goals + +- Filter sensitive environment variables from subprocesses +- No configuration means no filtering -- existing setups are unaffected + +## How + +### Configuration + +A new `external_commands` section in `settings.yaml` with two optional +lists: `keep_env` (allowlist) and `delete_env` (blocklist). Both +default to empty. + +```yaml +external_commands: + keep_env: + - "SOME_VARIABLE" + - "OTHER_*" + delete_env: + - "CREDENTIALS" + - "CI_TOKEN" +``` + +### Pattern matching + +Entries without `*` are exact matches. Entries ending with `*` are +prefix matches: `AWS_*` matches `AWS_REGION`, `AWS_SECRET_ACCESS_KEY`, +etc. A `*` in any other position is a validation error. A bare `*` is +only valid in `delete_env` (catch-all); in `keep_env` it is a +validation error. + +### Evaluation order + +`keep_env` is evaluated before `delete_env`. A variable matching both +is kept. + +For each variable in `os.environ`: + +1. If it is in the always-keep set -- **keep**, regardless of + configuration. The always-keep set contains variables required for + basic subprocess operation and proxy settings: `HOME`, `HOSTNAME`, + `LANG`, `LANGUAGE`, `LC_*`, `LOGNAME`, `NO_COLOR`, `PATH`, `SHELL`, + `USER`, `http_proxy`, `https_proxy`, `no_proxy`. +2. If any `keep_env` entry matches -- **keep**. +3. If any `delete_env` entry matches -- **delete**. +4. Otherwise -- **keep** (default passthrough). + +A `delete_env` entry of `*` acts as a catch-all that blocks everything +not matched by steps 1 or 2. + +Variables injected by fromager itself (`extra_environ`, +`build_environment`, package-level `env`) are never filtered. They are +applied after the filter runs. + +### API changes + +`external_commands.run()` currently has no access to `WorkContext` or +settings. Making the filter configuration available there will require +API changes to the function signature or module state. The specifics of +that change are out of scope for this proposal and will be handled by a +separate proposal for the `external_commands` API. + +### Examples + +Strip everything except what builds need: + +```yaml +external_commands: + keep_env: + - "CARGO_*" + delete_env: + - "*" +``` + +Remove a few known secrets, pass everything else: + +```yaml +external_commands: + delete_env: + - "CI_TOKEN" + - "REGISTRY_PASSWORD" + - "AWS_*" +``` diff --git a/docs/proposals/index.rst b/docs/proposals/index.rst index 75c368b0..501d1dfe 100644 --- a/docs/proposals/index.rst +++ b/docs/proposals/index.rst @@ -4,6 +4,7 @@ Fromager Enhancement Proposals .. toctree:: :maxdepth: 1 + filter-env new-patcher-config new-resolver-config release-cooldown diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index dbec132b..fc333440 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -1,7 +1,9 @@ +allowlist args backend backends backoff +blocklist canonicalize canonicalized changelog @@ -20,6 +22,7 @@ dir downloader env environ +exfiltrate filesystem fromager frontend @@ -41,6 +44,7 @@ numpy openssl platlib podman +passthrough pre prebuilt purelib @@ -50,6 +54,7 @@ pypi pyproject recurses repo +reproducibility scm sdist sdists @@ -60,6 +65,7 @@ stdin stdout subcommands subdirectory +sudoers submodule submodules subprocesses