Problem
Fromager's existing network isolation (run_network_isolation.sh) blocks outbound access during PEP 517 build hooks, preventing build-time supply chain attacks from phoning home. However, some attacks deliberately place malicious code in the package's runtime paths (e.g., __init__.py) instead of build hooks, so it only executes on import, not during build.
The May 2026 "Mini Shai-Hulud" campaign (mistralai/client-python#523) demonstrated this: mistralai and guardrails-ai were compromised with backdoors in __init__.py that downloaded a credential-stealing payload via urllib.request.urlopen() and executed it as a detached process. This attack vector is invisible to build-time monitoring because the malicious code never runs during wheel compilation.
Proposal
After pep517_build_wheel() produces the .whl but before add_extra_metadata_to_wheels(), install the wheel into a temporary virtualenv and run python -c "import <package>" under the same run_network_isolation.sh used for builds.
Key design decision -- behavior-only monitoring: import failures (ImportError, ModuleNotFoundError, etc.) are expected and ignored. Many legitimate packages cannot import in a build environment (GPU packages needing CUDA runtime, packages with unmet optional dependencies). The monitor only flags anomalous behavior during the import attempt:
- Network access attempts (blocked by existing namespace isolation)
- Writes to sensitive filesystem paths (
/tmp/, ~/.ssh/, ~/.config/)
- Unexpected subprocess spawning (
curl, wget, detached processes)
This avoids false positives without needing a per-package allowlist. Real-world import-time backdoors use except: pass and execute their payload before any import-dependent code, so behavior monitoring catches them regardless of whether the import itself succeeds.
Why this works for downstream consumers
In downstream build pipelines, this runs transparently before the post_build hook fires -- compromised wheels are caught before upload to a package registry. No downstream changes needed, no allowlist to maintain.
Related issues
References
Problem
Fromager's existing network isolation (
run_network_isolation.sh) blocks outbound access during PEP 517 build hooks, preventing build-time supply chain attacks from phoning home. However, some attacks deliberately place malicious code in the package's runtime paths (e.g.,__init__.py) instead of build hooks, so it only executes onimport, not during build.The May 2026 "Mini Shai-Hulud" campaign (mistralai/client-python#523) demonstrated this:
mistralaiandguardrails-aiwere compromised with backdoors in__init__.pythat downloaded a credential-stealing payload viaurllib.request.urlopen()and executed it as a detached process. This attack vector is invisible to build-time monitoring because the malicious code never runs during wheel compilation.Proposal
After
pep517_build_wheel()produces the.whlbut beforeadd_extra_metadata_to_wheels(), install the wheel into a temporary virtualenv and runpython -c "import <package>"under the samerun_network_isolation.shused for builds.Key design decision -- behavior-only monitoring: import failures (
ImportError,ModuleNotFoundError, etc.) are expected and ignored. Many legitimate packages cannot import in a build environment (GPU packages needing CUDA runtime, packages with unmet optional dependencies). The monitor only flags anomalous behavior during the import attempt:/tmp/,~/.ssh/,~/.config/)curl,wget, detached processes)This avoids false positives without needing a per-package allowlist. Real-world import-time backdoors use
except: passand execute their payload before any import-dependent code, so behavior monitoring catches them regardless of whether the import itself succeeds.Why this works for downstream consumers
In downstream build pipelines, this runs transparently before the
post_buildhook fires -- compromised wheels are caught before upload to a package registry. No downstream changes needed, no allowlist to maintain.Related issues
References