Run package installs in a phantom environment with canary credentials to detect supply-chain attacks.
Project description
ShieldPkg
Malicious npm packages steal credentials. ShieldPkg makes sure they only steal fake ones.
Supply-chain attacks like the XZ backdoor and the hundreds of typosquatting packages caught every month share one playbook: install, read ~/.aws/credentials, POST the key somewhere, and wait. ShieldPkg intercepts that playbook at the environment level — the malicious package runs, but every credential it touches is a monitored trap.
See it in action
shieldpkg demo
# Watch ShieldPkg catch a credential theft attempt in real time
shieldpkg demo plants a fake malicious npm package (evil-logger) in a temp directory, runs its postinstall script inside the phantom environment, and watches the circuit breaker kill it when the simulated canary fires. No npm network access required — works completely offline.
Pass --show-source to display the evil package's source before it runs, or --trigger-delay N to control how many seconds before the simulated canary fires (default 8).
What it does
- Phantom environment — creates a fake
$HOMEwith realistic-looking.aws/credentials,.ssh/id_rsa,.npmrc, and.gitconfig. Your real home directory is never visible to the subprocess. - Canary tokens — plants real AWS key pairs from canarytokens.org inside the phantom home. If a package exfiltrates them and makes even a single AWS API call, you get an alert with the source IP.
- Circuit breaker — polls for canary triggers while the command runs. If a token fires, the process is killed immediately and the event is logged.
Install
pip install shieldpkg
Requires Python 3.9+. Node.js and Rust/Cargo are optional (only needed for shieldpkg experiment).
Quick start
# One-time setup: create the phantom environment and plant canary credentials
shieldpkg init
# Run any package install command inside the phantom environment
shieldpkg run -- npm install some-package
shieldpkg run -- pip install some-package
shieldpkg run -- npx some-cli
# Check phantom home and canary token status
shieldpkg status
# Watch for canary alerts in real time (blocks; use a separate terminal)
shieldpkg monitor
If a canary fires during shieldpkg run, the process is killed and you see:
╔══════════════════════════════════════════════════════╗
║ THREAT DETECTED — Process killed ║
║ ║
║ A package attempted to access your credentials. ║
║ The process was killed before it could exfiltrate. ║
║ ║
║ Token: abc123def456… ║
║ IP: 198.51.100.42 ║
║ Channel: HTTP ║
║ ║
║ Your real credentials were not exposed. ║
╚══════════════════════════════════════════════════════╝
How it works
- Env sanitizer strips
AWS_*,*_TOKEN,*_SECRET,*_PASSWORD,DATABASE_URL, andGITHUB_TOKENfrom the subprocess environment before exec. The phantom$HOMEis injected instead. - Canary polling runs on a background thread during
shieldpkg run, calling canarytokens.org every 5 seconds (configurable). On trigger,SIGKILLis sent to the process group. - Audit log at
~/.shieldpkg/audit.logrecords every init, monitor start, trigger, and kill event in append-only JSON-lines format.
Commands
| Command | Description |
|---|---|
shieldpkg init |
Create phantom home, generate canary AWS credentials |
shieldpkg demo [--trigger-delay N] [--show-source] |
Simulate a supply-chain attack and watch the kill |
shieldpkg run -- <cmd> |
Run <cmd> in phantom env with active monitoring |
shieldpkg status |
Show phantom home and canary token status |
shieldpkg monitor [--interval N] |
Poll canarytokens.org every N seconds (default 60) |
shieldpkg audit [--last N] [--triggered-only] |
Inspect the audit log |
shieldpkg experiment --packages <list> |
Measure JS→Rust transpilation via Strand (research) |
shieldpkg experiment (research feature)
Evaluates whether Strand-Rust-Coder-14B can reliably transpile npm packages to Rust with verified behavioural equivalence. Requires Ollama running locally and cargo installed.
shieldpkg experiment --packages ms,left-pad,is-even,uuid --fuzz-inputs 500
Configuration
~/.shieldpkg/config.yaml (created automatically on first run):
monitor_interval: 5 # seconds between canary polls during shieldpkg run
What it doesn't do
- Not a scanner — ShieldPkg does not analyse package source code or flag suspicious imports. It assumes packages will run and focuses on limiting damage.
- Not a firewall — outbound network calls are not blocked. A malicious package can still exfiltrate the phantom credentials (that's how detection works), but the credentials it steals are traps.
- Not a sandbox — the filesystem outside
$HOMEis visible. If a package targets/etc/passwd,/proc, or absolute paths to well-known credential locations, ShieldPkg won't stop it reading those files. - Not a replacement for
npm audit— use both. ShieldPkg is a last line of defence, not a substitute for keeping dependencies up to date.
Development
git clone https://github.com/yourname/shieldpkg-core
cd shieldpkg-core
pip install -e ".[dev]"
pytest -v
Exit codes
| Code | Meaning |
|---|---|
| 0 | Command completed cleanly |
| 1 | User error (bad arguments, not initialised) |
| 2 | System error (Ollama not running, cargo not installed, etc.) |
When shieldpkg run detects a threat, it exits 1 after killing the process.
Docs
| Document | Description |
|---|---|
| docs/how-it-works.md | Phantom env, canary tokens, circuit breaker, and honest limitations |
| docs/faq.md | Common questions about privacy, compatibility, and workflow |
| docs/roadmap.md | Team vault, Strand Rust replacement, credential proxy, network effect |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shieldpkg-0.1.0.tar.gz.
File metadata
- Download URL: shieldpkg-0.1.0.tar.gz
- Upload date:
- Size: 56.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e566268d29931e5e2b5e89c69cc468c56cee5b6fcb24f9eadd8e4c246756ce0
|
|
| MD5 |
ea81e47570a83e2a2ae6c15d3e3f9221
|
|
| BLAKE2b-256 |
51698b98de560aed9a6fa3e49d3b7292e77a1498fa64a90548ddf39701a59bce
|
File details
Details for the file shieldpkg-0.1.0-py3-none-any.whl.
File metadata
- Download URL: shieldpkg-0.1.0-py3-none-any.whl
- Upload date:
- Size: 46.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60ad9134618d932f97f7f0a7d1be9d37f8a1992aa922657bcc44a79eee4de344
|
|
| MD5 |
ab6c11e9c2772c66af8b39dd6d8b1427
|
|
| BLAKE2b-256 |
49c53d18c573d044b93902b527a5d0cc674db26b42f8a4f477bc72ecd1673461
|