From agent-infra-security
Audits dependency configs for supply chain risks like unpinned versions, missing lockfiles, postinstall scripts in package.json, requirements.txt, Gemfile, go.mod, Cargo.toml, pom.xml. Hardens with pinning, SBOM, signing best practices.
npx claudepluginhub makash/agent-infra-security --plugin agent-infra-securityThis skill uses the workspace's default tool permissions.
Proactively audit and harden your project's dependency management to prevent supply chain attacks.
Provides software supply chain security guidance on SBOM generation, SLSA framework, dependency scanning, SCA tools, and protections against attacks like dependency confusion and typosquatting.
Enforces supply chain security by flagging unpinned dependencies, missing lockfiles, unverified installs, and absent CI vulnerability scans across package managers.
Scans project dependencies across ecosystems for vulnerabilities and license risks, generates SBOMs, assesses supply chain security, and recommends remediation.
Share bugs, ideas, or general feedback.
Proactively audit and harden your project's dependency management to prevent supply chain attacks.
This skill is preventive, not reactive. For active incident response (compromised package, IOC hunting, credential rotation), use the ecosystem-specific skills: npm-supply-chain-response, pypi-supply-chain-response, github-actions-supply-chain-response, or the generic supply-chain-security-check.
Walk the user through each category. Adapt commands to the detected ecosystem(s) in the project.
Goal: Every dependency resolves to exactly one version. No ranges, no floating tags.
| Ecosystem | Risky pattern | Safe pattern |
|---|---|---|
| npm | "axios": "^1.14.0" or "~1.14.0" | "axios": "1.14.0" (use --save-exact) |
| Python | requests>=2.28 or requests | requests==2.28.0 |
| Ruby | gem 'rails', '~> 7.0' | gem 'rails', '7.0.8' |
| Go | Uses go.sum for integrity (automatic) | Verify go.sum is committed |
| Rust | serde = "1" (allows minor bumps) | serde = "=1.0.197" |
| Java | <version>[1.0,2.0)</version> | <version>1.0.3</version> |
| .NET | Version="1.*" | Version="1.2.3" |
| GitHub Actions | uses: actions/checkout@v4 | uses: actions/checkout@<SHA> # v4.1.1 |
Audit commands:
# npm — find non-exact versions
grep -E '"\^|"~|">=|">' package.json
# Python — find unpinned or range-pinned
grep -vE '==|#|^$|^-' requirements.txt 2>/dev/null
# GitHub Actions — find tag-based references
grep -rn 'uses:.*@v' .github/workflows/ 2>/dev/null
grep -rn 'uses:.*@main' .github/workflows/ 2>/dev/null
Goal: Lockfiles exist, are committed, and used in CI.
| Ecosystem | Lockfile | CI command (lockfile-only) |
|---|---|---|
| npm | package-lock.json | npm ci (not npm install) |
| Yarn | yarn.lock | yarn install --frozen-lockfile |
| pnpm | pnpm-lock.yaml | pnpm install --frozen-lockfile |
| Python (pip-tools) | requirements.txt (compiled) | pip install -r requirements.txt |
| Python (uv) | uv.lock | uv sync --frozen |
| Python (Poetry) | poetry.lock | poetry install --no-update |
| Ruby | Gemfile.lock | bundle install --frozen |
| Go | go.sum | go mod verify |
| Rust | Cargo.lock | Commit Cargo.lock for binaries |
Lockfiles with hashes (stronger — detects tampered packages):
# Python
pip-compile --generate-hashes requirements.in
uv pip compile --generate-hashes requirements.in
# npm
# package-lock.json includes integrity hashes by default
# Lockfile lint (npm)
npx lockfile-lint --path package-lock.json --type npm --allowed-hosts npm
Audit:
# Check if lockfiles exist and are committed
git ls-files | grep -iE 'lock|\.sum$'
# Check CI for lockfile-only commands
grep -rn 'npm ci\|--frozen-lockfile\|--no-update\|go mod verify' .github/workflows/ .gitlab-ci.yml Jenkinsfile 2>/dev/null
Goal: Disable automatic execution of arbitrary code during package install.
npm postinstall — the primary vector for npm supply chain attacks:
# Disable globally
npm config set ignore-scripts true
# Or in .npmrc (committed to repo)
echo "ignore-scripts=true" >> .npmrc
# Then selectively rebuild trusted native deps
npm rebuild sharp esbuild
# Audit which packages have postinstall
npm query ':attr(scripts, [postinstall])' 2>/dev/null | jq '.[].name'
Python .pth files — execute on every interpreter startup:
SITE=$(python -c "import site; print(site.getsitepackages()[0])")
find "$SITE" -name "*.pth" -exec grep -l "base64\|subprocess\|exec\|eval\|compile" {} \;
Ruby extconf.rb — native extension build scripts:
find vendor/bundle -name "extconf.rb" 2>/dev/null | head -20
Goal: Automated checks on every PR and scheduled scans.
# GitHub Actions example — npm
- run: npm audit --omit=dev
# GitHub Actions example — Python
- run: pip-audit
# GitHub Actions example — Go
- run: govulncheck ./...
# GitHub Actions example — Rust
- run: cargo audit
# GitHub Actions example — Ruby
- run: bundle audit check --update
Multi-ecosystem with Trivy:
- uses: aquasecurity/trivy-action@<SHA>
with:
scan-type: 'fs'
scan-ref: '.'
Goal: Verify packages come from who they claim to come from.
npm provenance:
# Verify signatures on installed packages
npm audit signatures
# Publish your own packages with provenance
# In GitHub Actions:
# permissions:
# id-token: write
# contents: read
# - run: npm publish --provenance
Python Trusted Publishing:
Sigstore (multi-ecosystem):
# Sign
cosign sign-blob --yes artifact.tar.gz
# Verify
cosign verify-blob artifact.tar.gz --signature artifact.tar.gz.sig --certificate artifact.tar.gz.pem
Container image signing:
# Sign
cosign sign <IMAGE_DIGEST>
# Verify
cosign verify <IMAGE_DIGEST>
Goal: Minimize blast radius if a dependency runs malicious code during install.
Don't do this:
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET }}
steps:
- run: npm ci # <-- every step has cloud credentials
- run: npm test
- run: npm run deploy
Do this instead:
steps:
- run: npm ci # No secrets
- run: npm test # No secrets
- run: npm run deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET }}
Use OIDC instead of long-lived credentials:
permissions:
id-token: write
contents: read
- uses: aws-actions/configure-aws-credentials@<SHA>
with:
role-to-assume: arn:aws:iam::123456789:role/deploy
aws-region: us-east-1
Use GitHub Environments with protection rules to gate access to production secrets.
Goal: Know your full dependency tree so you can answer "am I affected?" in seconds.
# Python
pip install cyclonedx-bom
cyclonedx-py requirements -i requirements.txt -o sbom.json
# npm
npx @cyclonedx/cyclonedx-npm --output-file sbom.json
# Go
cyclonedx-gomod mod -json -output sbom.json
# Rust
cargo cyclonedx
# Multi-ecosystem with Syft
syft . -o cyclonedx-json > sbom.json
Store SBOMs as CI artifacts. When the next advisory drops, grep the SBOM instead of auditing every environment.
Goal: Stay current without exposing yourself to zero-day compromises.
--exclude-newer to freeze the supply chain timeline:
uv pip install --exclude-newer "2026-03-28T00:00:00Z" <PACKAGE>
npm:
# .npmrc
ignore-scripts=true
audit=true
fund=false
pip:
# Require hashes for all installs
pip install --require-hashes -r requirements.txt
Corepack (Node.js):
corepack enable
corepack prepare npm@10.9.0 --activate
Prevents a compromised global npm binary from being used.
Produce a checklist report for the project:
## Supply Chain Security Audit — [Project Name]
### Version Pinning: [PASS/WARN/FAIL]
- [Details]
### Lockfile Integrity: [PASS/WARN/FAIL]
- [Details]
### Install Hooks: [PASS/WARN/FAIL]
- [Details]
### Vulnerability Scanning: [PASS/WARN/FAIL]
- [Details]
### Provenance/Signing: [PASS/WARN/FAIL]
- [Details]
### CI Secret Scoping: [PASS/WARN/FAIL]
- [Details]
### SBOM: [PASS/WARN/FAIL]
- [Details]
### Update Strategy: [PASS/WARN/FAIL]
- [Details]
### Package Manager Hardening: [PASS/WARN/FAIL]
- [Details]
### Recommended Actions (priority order)
1. [Most critical fix]
2. [Next fix]
...
ignore-scripts in npm + scoped CI secrets. Start there.