Three new self-contained, runnable threat demonstrations under
examples/, continuing the batch started in 583a78c. Each example
has README.md + run-*.mjs + expected-findings.md and uses
state-isolation discipline so the user's real cache/state files
are never polluted.
- examples/supply-chain-attack/ — two-layer demonstration:
pre-install-supply-chain (PreToolUse) blocks compromised
event-stream version 3.3.6 and emits a scope-hop advisory for
the @evilcorp scope; dep-auditor (DEP scanner, offline) flags
5 typosquat dependencies plus a curl-piped install-script
vector in the fixture package.json. Maps to LLM03/LLM05/ASI04.
- examples/poisoned-claude-md/ — all 6 memory-poisoning detectors
fire on a deliberately poisoned CLAUDE.md plus a fixture
agent file under .claude/agents (E15/v7.2.0 surface):
detectInjection, detectShellCommands, detectSuspiciousUrls,
detectCredentialPaths, detectPermissionExpansion,
detectEncodedPayloads. No agent runtime needed — scanner
imported directly. Maps to LLM01/LLM06/ASI04.
- examples/bash-evasion-gallery/ — one disguised variant per
T1 through T9 evasion technique fed through pre-bash-destructive,
verified BLOCK after bash-normalize strips the evasion. T8
base64-pipe-shell uses its own BLOCK_RULE. The canonical
destructive form uses a path token rather than the bare slash
(regex word-boundary requires it). Source-string fragmentation
pattern reused from the e2e attack-chain test. Maps to
LLM06/ASI01/LLM01.
Plugin README "Other runnable examples" section + plugin
CLAUDE.md "Examples" table + CHANGELOG Unreleased/Added
all updated. Marketplace root README unchanged
([skip-docs] for marketplace-level gate — plugin's outward
coverage is unchanged, only demonstrations were added).
2.5 KiB
2.5 KiB
Expected Findings — Supply Chain Attack Walkthrough
This is the testable contract. run-supply-chain.mjs exits 0 only
when every row matches.
Stage A — pre-install-supply-chain hook
| Case | Command | Exit | stderr/stdout must contain |
|---|---|---|---|
| 1 | npm install event-stream@3.3.6 |
2 | COMPROMISED and a reference to the socket.dev URL |
| 2 | npm install @evilcorp/lodash |
0 | SCOPE-HOPPING SUSPECTED advisory |
| 3 | npm install lodash |
0 | (no advisory required) |
The hook's BLOCK output goes to stderr with the literal prefix
🛑 BLOCKED: Supply chain risk detected [npm]. Advisories use the
prefix ⚠️ Supply chain advisory [npm]:. Both are checked
case-insensitively by run-supply-chain.mjs.
Stage B — dep-auditor on fixture/package.json
Findings array MUST contain at least:
| Severity | Title pattern | Source |
|---|---|---|
| HIGH | Possible typosquatting: "expresss" vs "express" (edit distance 1) |
typosquat — Levenshtein 1 |
| MEDIUM | Potential typosquatting: "loadsh" vs "lodash" (edit distance 2) |
typosquat — Levenshtein 2 |
| MEDIUM | Potential typosquatting: "axois" vs "axios" (edit distance 2) |
typosquat — Levenshtein 2 |
| HIGH | Possible typosquatting: "reaact" vs "react" (edit distance 1) |
typosquat — Levenshtein 1 |
| HIGH | Possible typosquatting: "chalkk" vs "chalk" (edit distance 1) |
typosquat — Levenshtein 1 (devDependencies) |
| HIGH | Suspicious npm install hook: scripts.postinstall contains network/exec patterns |
install-script heuristic |
Total: 6 findings.
run-supply-chain.mjs asserts:
>= 4typosquat findings (allowing minor changes in dep-auditor)>= 1install-script finding
Side effects
- No real
npm installruns — only synthetic JSON sent to the hook - No write to the user's
node_modules/ - No network call (deterministic mode); OSV.dev path is not exercised
- The fixture
package.jsonis parsed read-only
Notes for forks
If a fork extends NPM_COMPROMISED or top-packages.json:
- The compromised-version block (case 1) may match a different list entry — adjust the regex if needed
- The typosquat findings are tied to the top-100 list. Adding/removing
entries near
chalk/react/express/lodash/axiosmay change the severity from MEDIUM to HIGH or vice-versa - The install-script heuristic regex lives in
dep-auditor.mjs— if reworded, update the test pattern inrun-supply-chain.mjs