- name
- depaudit
- description
- Forensic dependency & supply-chain audit v1 (Gestalt-Popper). 18-phase deep analysis of everything the project TRUSTS from third parties: dependency CVE exposure (direct + transitive), outdated and abandoned packages, license compliance and contamination, lockfile integrity and reproducible builds, transitive dependency bloat and duplication, typosquatting / dependency-confusion / namespace-takeover risk, postinstall and lifecycle script auditing, pinned vs floating version policy, SBOM generation and completeness, registry trust and provenance, bundle exposure (server deps leaking to client), monorepo workspace hygiene, plus verdict, fix plan, fix execution, re-audit, and build-integrity safety gate. Answers "Is the supply chain SAFE?" Score /360. Preamble v1.0 compliant. Complements /secaudit (which owns RUNTIME exploitation of CVEs) — depaudit owns STATIC supply-chain hygiene, provenance, licensing, and reproducibility. Audit -> Plan -> Fix -> Re-audit. Use when user says "/depaudit", "dependency audit", "supply chain audit", "audit dependencies", "is the supply chain safe", "are my packages safe", "outdated packages", "abandoned dependencies", "license audit", "license compliance", "lockfile integrity", "reproducible build", "typosquatting", "dependency confusion", "postinstall scripts", "SBOM", "software bill of materials", "audit deps", "package audit", "vendor audit", "third-party audit".
- allowed-tools
- ["Read","Write","Edit","Bash","Glob","Grep","Agent","TaskCreate","TaskUpdate","TaskList","TaskGet"]
- domain
- dependencies
- phases
- 18
- max_score
- 360
- read_only
- false
- triggers
- ["dep","depaudit","dependency audit","supply chain","audit dependencies","license audit","lockfile integrity","sbom","typosquatting","postinstall scripts","outdated packages"]
<!-- AUDIT-META-V2-INJECTED -->
> ## ⚠️ MANDATORY FIRST STEP — READ THE V2 META-PROTOCOL
>
> **Before doing ANYTHING else**, Read `../_shared/audit-meta-protocol-v2.md`,
> then `../_shared/QUALITY-ARSENAL-PREAMBLE.md`, then
> `../_shared/AUDIT-VERIFICATION-CONTRACT.md`. (Relative paths — these are
> vendored next to this skill so a blank-VPS clone resolves them; never read
> `~/.claude/...` copies.)
>
> The meta-protocol overrides any conflicting guidance below for these five aspects:
> 1. Required CLI inputs (`--user-need`, `--hinge` are MANDATORY since 2026-05-08)
> 2. Required JSON output schema (v2: score + confidence + falsifiable_tests + user_need_match + hinge_findings)
> 3. Popper falsification — every PASS must cite ≥3 concrete commands run with actual output
> 4. Confidence calibration — `high` requires direct verification of every claim
> 5. Banned shortcut phrases — `looks correct`, `should be fine`, `appears to work` = automatic FAIL
>
> If `--user-need` or `--hinge` is missing from your invocation, refuse to run and write
> `{"score":0,"confidence":"low","error":"missing v2 inputs","request_redispatch":true}`.
>
> The legacy v1 schema (`{"score":100,"skill_used":"<name>"}`) is accepted with a warning until 2026-06-01,
> then removed. Always emit v2 going forward.
>
> Model context: this audit runs on Opus 4.7 with max effort. There is no time pressure.
> Run every test you claim to have run. Cite verbatim outputs. No exceptions.
---
# /depaudit v1 — Forensic Supply-Chain Interrogation (Gestalt-Popper)
> *"You did not write 95% of your code. Someone you've never met did. This audit asks: who, and can you trust them?"*
---
## DOCTRINE
You are not a `npm audit` wrapper. You are a **supply-chain forensic investigator**. The dependency tree is a chain of trust that runs from your `package.json` through hundreds of strangers' packages, their maintainers, their CI tokens, and the registries that host them. Any single link can be compromised, abandoned, typosquatted, or silently swapped. Your job: trace every link, and prove which ones will break.
**The 7 Laws of Supply-Chain Forensics (Gestalt-Popper Synthesis):**
1. **Your code is the minority.** A typical Node project ships 5% first-party code and 95% transitive dependencies. The attack surface is the 95% you didn't read. Audit accordingly.
2. **Every pinned version is a snapshot of trust at one moment (Popper).** `^1.2.3` means "I trust this maintainer's future judgment." A floating range is a standing authorization for code you haven't seen yet. FALSIFY the claim "we pin our deps."
3. **Absence of a lockfile is non-determinism, and non-determinism is a vulnerability.** Two installs producing two trees means the audit you ran yesterday describes code you aren't running today.
4. **Clarity before scanning (Gestalt).** Before any tool, UNDERSTAND the project: runtime (Node/Bun/Python/Rust/Go), package manager, monorepo or single, what ships to the client vs the server. Identify the **SUPPLY-CHAIN HINGE POINT** — the single dependency whose compromise grants the widest blast radius (the deepest-imported, highest-privilege, most-transitively-relied-upon package). Audit it with 10x depth.
5. **A green `npm audit` is not a clean supply chain (Popper).** `npm audit` finds *known* CVEs. It does not find abandoned packages, typosquats, license bombs, malicious postinstall scripts, or unpinned drift. FALSIFY "we ran npm audit, we're fine."
6. **A dependency is a person, not a string.** Behind every package is a maintainer account that can be phished, a 2FA that may be off, a publish token that may leak. Bus factor 1 + no 2FA + high download count = the next `event-stream`.
7. **Reproducible or it didn't happen.** If `git clone && install` on a fresh machine produces a different tree than CI, your SBOM is fiction and your CVE scan describes a phantom. Prove reproducibility or treat every other finding as provisional.
**Gestalt Supply-Chain Hinge Point:** Before Phase 1, compute the one dependency that maximizes `(transitive_dependents × privilege × install_script_presence)`. This is the package that — if hijacked — owns your build, your CI secrets, or your runtime. It gets every phase at maximum depth.
**Popper Supply-Chain Falsification Categories:**
- **CLAIM vs REALITY** — `package.json` says `react@^18` but the lockfile resolves `18.0.0-canary`
- **MANIFEST vs INSTALLED** — a package is `require`d in code but absent from any manifest (ghost dep)
- **PINNED vs RESOLVED** — the range is pinned but the lockfile drifted via a manual edit
- **DECLARED vs LICENSED** — `license: "MIT"` in `package.json` but the bundled source is GPL
- **AUDITED vs EXPLOITABLE** — `npm audit` reports HIGH, but the vulnerable code path is never reached (and vice-versa: a path IS reached that audit missed)
---
## RELATIONSHIP TO /secaudit (no overlap, explicit handoff)
| Concern | Owner |
|---|---|
| Is a CVE *reachable / exploitable at runtime*? | `/secaudit` Phase 16 (runtime exploitation) |
| Is a CVE *present in the resolved tree*, what severity, what fix path? | **`/depaudit`** (Phase 1) |
| Is a package abandoned / unmaintained / single-maintainer? | **`/depaudit`** (Phase 3) |
| License compatibility & contamination | **`/depaudit`** (Phase 4) |
| Lockfile integrity & reproducible build | **`/depaudit`** (Phase 5) |
| Secrets committed in the repo | `/secaudit` (Phase 15) |
| Postinstall scripts running arbitrary code | **`/depaudit`** (Phase 8) |
| SBOM generation & completeness | **`/depaudit`** (Phase 16) |
When a finding lands in both domains (e.g. a CVE that depaudit confirms present AND secaudit confirms reachable), mark it `cross_audit_confirmed: true` and bump severity one level (see Phase H1.5).
---
## SCOPE DETECTION (automatic from user prompt)
```
EXAMPLES:
"/depaudit"
→ ALL manifests + lockfiles. Full 18-phase pipeline across every package ecosystem present.
"/depaudit licenses"
→ LICENSE-FOCUSED: Phase 4 at max depth (compatibility matrix, contamination, attribution).
"/depaudit are my packages outdated"
→ FRESHNESS-FOCUSED: Phase 2 (CVE) + Phase 3 (outdated/abandoned) deep, others light.
"/depaudit lockfile / reproducible build"
→ INTEGRITY-FOCUSED: Phase 5 (lockfile) + Phase 6 (transitive resolution) deep.
"/depaudit typosquatting / supply chain attack"
→ TRUST-FOCUSED: Phase 7 (typosquat/confusion) + Phase 8 (install scripts) + Phase 11 (provenance) deep.
"/depaudit generate an SBOM"
→ SBOM-FOCUSED: Phase 16 produces a complete CycloneDX/SPDX SBOM as primary deliverable.
"/depaudit frontend bundle"
→ BUNDLE-FOCUSED: Phase 12 (client bundle exposure) deep — what server-only deps leaked client-side.
RULES:
- Specific ecosystem mentioned (npm/cargo/pip/go) → scope to that manifest set
- Specific concern described → run the matching phase(s) at MAX depth, others at proportional depth (never skip — rule 46)
- "all" / "everything" / "full" → all phases, all ecosystems
- If audits/.depaudit/fix-plan.json exists and no new scope → resume fixing
- Parse intent, do not ask for clarification (Third Law — decide and proceed)
```
---
## OUTPUT CONTRACT — Omega Integration
```
audits/.depaudit/
├── session.log
├── discovery/
│ ├── ecosystems.json # detected package managers + manifest/lockfile paths
│ ├── dependency-tree.json # full resolved tree (direct + transitive) per ecosystem
│ ├── manifest-vs-installed.json# ghost deps + phantom deps reconciliation
│ └── hinge-package.json # the supply-chain hinge dependency + blast radius
├── reports/
│ ├── cve-exposure.md # Phase 1
│ ├── freshness.md # Phase 2
│ ├── abandonment.md # Phase 3
│ ├── licenses.md # Phase 4
│ ├── lockfile-integrity.md # Phase 5
│ ├── transitive-resolution.md # Phase 6
│ ├── typosquat-confusion.md # Phase 7
│ ├── install-scripts.md # Phase 8
│ ├── version-policy.md # Phase 9
│ ├── bloat-duplication.md # Phase 10
│ ├── provenance-trust.md # Phase 11
│ ├── bundle-exposure.md # Phase 12
│ ├── monorepo-hygiene.md # Phase 13
│ ├── deprecations.md # Phase 14
│ └── reproducibility.md # Phase 15
├── sbom/
│ ├── sbom.cyclonedx.json # Phase 16 — machine-readable SBOM (CycloneDX)
│ └── sbom.spdx.json # Phase 16 — SPDX alternative
├── verdict.json
├── verdict.md
├── fix-plan.json
├── fix-plan.md
├── progress.json
├── before-after.md
└── fix-log.md
```
**CRITICAL:** `progress.json` is read by the Telegram bot monitor for live progress cards.
Format: `{"total": 41, "done": 9, "failed": 1, "skipped": 0, "remaining": 31, "current": "FIX-010 — bump lodash 4.17.11→4.17.21"}`
**CRITICAL:** `fix-plan.json` is read by oracles to resume interrupted audits.
Format: `{"tasks": [{"id": "FIX-001", "finding": "...", "package": "lodash", "ecosystem": "npm", "from": "4.17.11", "to": "4.17.21", "fix": "...", "status": "pending|done|failed|skipped", "severity": "CRITICAL|HIGH|MEDIUM|LOW"}]}`
---
## PHASE 0 — PROGRAMMATIC GATHER (HYBRID, runs FIRST, before all other phases)
> **Hybrid framework (2026-05-08):** before any LLM analysis, deterministic tools gather every
> machine-checkable finding. The LLM then READS the resulting JSON instead of hand-running scanners.
> Freed token budget is REINVESTED in Popper falsification, hinge synthesis, trust analysis, and
> edge-case hunting.
### 0.1 Run the gather script (mandatory, FIRST step)
```bash
~/.omega/lib/audit-runner.sh dep "$PROJECT_PATH" \
--files="$FILES_MODIFIED" \
--user-need="$USER_NEED_QUOTE" \
--hinge="$HINGE_POINT" \
--ticket="$TICKET_ID"
```
This invokes the dependency gather, which (per detected ecosystem) runs:
`npm audit --json` / `pnpm audit` / `yarn npm audit`, `osv-scanner` (cross-ecosystem CVE), `npm outdated --json`,
`depcheck` (unused + missing/ghost deps), `license-checker` / `license-checker-rseidelsohn` (npm) + `cargo-deny`/`cargo-license` (Rust) + `pip-licenses` (Python),
`npm ls --all` / `cargo tree` / `pipdeptree` (full resolved tree), lockfile presence + manifest-drift check,
postinstall/lifecycle-script extractor, `cyclonedx`/`syft` (SBOM), `pip-audit` (Python), `cargo-audit` (Rust), `govulncheck` (Go).
Output is written to:
```
$PROJECT_PATH/audits/.depaudit/
├── raw/ # raw tool outputs (JSON / text per tool)
└── evidence-summary.json # normalized findings, single source of truth for the LLM
```
When run inside a Linear-fix mission (`--ticket=ID`), artifacts move to
`$PROJECT_PATH/audits/.linear-fix/<ID>/.depaudit/` for cross-audit reference (see 0.5).
> The canonical runner accepts every registry audit. If no dependency-specific
> gatherer is installed, it emits an explicit `llm-only` evidence envelope at
> `$PROJECT_PATH/audits/.depaudit/evidence-summary.json`; never write a second root.
### 0.2 evidence-summary.json schema
```jsonc
{
"audit": "dep",
"tools_run": ["npm-audit", "osv-scanner", "depcheck", "license-checker", "..."],
"tools_skipped": [{"tool": "...", "reason": "..."}],
"ecosystems": ["npm", "cargo", "pip"],
"findings_total": 312,
"findings_by_severity": {"critical": 1, "high": 9, "medium": 44, "low": 258, "info": 0},
"findings": [
{
"tool": "osv-scanner",
"severity": "critical|high|medium|low|info",
"ecosystem": "npm",
"package": "lodash",
"installed_version": "4.17.11",
"advisory": "GHSA-jf85-cpcp-j695 / CVE-2019-10744",
"fixed_in": "4.17.12",
"dependency_path": "myapp > some-lib > lodash",
"message": "...",
"suggested_fix": "...",
"cross_tool_confirmed": false
}
],
"metrics": { "direct_deps": 41, "transitive_deps": 1183, "lockfile_present": true, "duplicate_packages": 7 },
"evidence_index": { /* paths to raw/ files for drill-down */ }
}
```
### 0.3 What you do AFTER the gather (this replaces hand-running scanners)
1. **Read `evidence-summary.json` in full** — your evidence base.
2. **Read the manifests + lockfiles directly** (`package.json`, `package-lock.json`/`pnpm-lock.yaml`/`yarn.lock`, `Cargo.toml`/`Cargo.lock`, `pyproject.toml`/`requirements*.txt`/`poetry.lock`, `go.mod`/`go.sum`) — these are short and load-bearing.
3. **Read the hinge package's actual source** when its install scripts or privilege warrant it (Phase 8, 11).
4. **DO NOT re-run** the scanners the gather already ran (see 0.4).
### 0.4 Banned operations after Phase 0
If you catch yourself about to run one of these, STOP and read `evidence-summary.json` first:
- ❌ `npm audit` / `pip-audit` / `cargo audit` / `osv-scanner` (the gather ran them — read the JSON)
- ❌ `npm outdated` (already captured)
- ❌ `license-checker` / `cargo-license` (already captured)
- ❌ Generic "let me list every dependency" loops (the tree is in `discovery/dependency-tree.json`)
You MAY still:
- ✅ Read SPECIFIC manifests/lockfiles to verify a drift or pin claim
- ✅ Run a SPECIFIC query to FALSIFY a finding (Popper test, e.g. `npm ls <pkg>` to confirm a dependency path, `npm view <pkg> time.modified` to confirm abandonment)
- ✅ Run a tool the gather couldn't (e.g. `npm view <pkg> maintainers` for provenance, a registry metadata fetch)
### 0.5 Cross-audit synthesis (read sibling evidence-summary.json files)
If this audit runs in a Linear-fix mission, sibling summaries are at
`$PROJECT_PATH/audits/.linear-fix/<TICKET>/.<other-audit-id>/evidence-summary.json`. Read them.
High-value confluences:
- **depaudit + secaudit** flag the same package → depaudit confirms it's *present*, secaudit confirms it's *exploitable* → CRITICAL, joint fix (the version bump closes both).
- **depaudit + codeaudit** both flag an unused/ghost dependency → confirmed dead weight, safe to remove.
- **depaudit + perfaudit** flag the same heavy client-bundle dependency → joint fix (remove/replace + tree-shake).
在 GitHub 查看