feat(security): package legitimacy gate against slopsquatting (#3215)
* feat(security): package legitimacy gate against slopsquatting (#2827) GSD's research → plan → execute pipeline had no install-time legitimacy gate: a hallucinated package name that passes `npm view` could flow all the way to `gsd-executor` running `npm install <malicious-pkg>` with no human checkpoint. This PR closes that gap. Changes: - gsd-phase-researcher: runs slopcheck on every recommended package; emits `## Package Legitimacy Audit` table; strips [SLOP] packages; ecosystem-specific verification (pip/npm/cargo); WebSearch-sourced packages tagged [ASSUMED]; ctx7 fallback uses `command -v` guard instead of `npx --yes` - gsd-planner: injects `checkpoint:human-verify` before [ASSUMED]/[SUS] installs; adds T-{phase}-SC STRIDE row to <threat_model> template; ctx7 fallback also uses `command -v` guard - gsd-executor: RULE 3 excludes package installs from auto-fix; failed installs surface as checkpoints, never silent substitutions - tests/package-legitimacy-gate.test.cjs: 24 structural assertions covering the full gate (node:test + node:assert, no raw .includes()) - docs: USER-GUIDE, COMMANDS, ARCHITECTURE updated with gate description - .changeset: Security fragment for v1.51 release notes Closes #2827 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: expand Package Legitimacy Gate documentation Add full user-facing depth to the gate docs across USER-GUIDE, COMMANDS, and ARCHITECTURE: - USER-GUIDE: rewrite gate section with concrete RESEARCH.md/PLAN.md examples, slopcheck verdict table, [ASSUMED] WebSearch tagging explanation, slopcheck-unavailable troubleshooting, and graceful degradation behavior - COMMANDS.md: expand /gsd-plan-phase gate note with verdict bullets; add install-failure checkpoint behavior to /gsd-execute-phase - ARCHITECTURE.md: expand gate section with threat model rationale, layer table, claim provenance integration, ecosystem coverage, and graceful degradation semantics Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(security): harden package legitimacy checkpoint semantics * fix(planner): satisfy size gates and tighten package gate wording --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -721,6 +721,87 @@ The `security.cjs` module scans for known injection patterns (role overrides, in
|
||||
|
||||
---
|
||||
|
||||
### Package Legitimacy Gate (v1.51)
|
||||
|
||||
AI coding tools hallucinate package names. Attackers pre-register those names on npm, PyPI, and crates.io with malicious post-install scripts — a technique called *slopsquatting*. A hallucinated name that passes `npm view` looks legitimate, so it would flow undetected through GSD's research → plan → execute pipeline all the way to `npm install <malicious-pkg>` running on your machine.
|
||||
|
||||
v1.51 adds a three-layer gate that stops this before it reaches your shell.
|
||||
|
||||
#### What you'll see
|
||||
|
||||
**In RESEARCH.md** — every phase that recommends external packages now includes a `## Package Legitimacy Audit` table:
|
||||
|
||||
```markdown
|
||||
## Package Legitimacy Audit
|
||||
|
||||
| Package | Registry | Age | Downloads | Source Repo | slopcheck | Disposition |
|
||||
|---------|----------|-----|-----------|-------------|-----------|-------------|
|
||||
| express | npm | 13 yrs | 100M+/wk | github.com/expressjs/express | [OK] | Approved |
|
||||
| some-new-util | npm | 3 days | 47 | none | [SLOP] | REMOVED |
|
||||
| api-bridge | npm | 6 mo | 1.2k/wk | github.com/user/api-bridge | [SUS] | Flagged |
|
||||
|
||||
**Packages removed due to slopcheck:** some-new-util
|
||||
**Packages flagged as suspicious:** api-bridge — planner will require human verification before install
|
||||
```
|
||||
|
||||
`[SLOP]` packages are removed from RESEARCH.md entirely. They never reach the planner.
|
||||
|
||||
**In PLAN.md** — if a package is tagged `[ASSUMED]` (sourced from WebSearch, not registry-verified) or `[SUS]` (slopcheck suspicious), the plan includes a verification checkpoint *before* the install task:
|
||||
|
||||
```xml
|
||||
<task type="checkpoint:human-verify">
|
||||
<what-built>Package verification required before install</what-built>
|
||||
<how-to-verify>
|
||||
Verify these packages before proceeding:
|
||||
- `api-bridge` [SUS — 6 months old, 1.2k downloads/week, GitHub repo present]
|
||||
Check: https://npmjs.com/package/api-bridge
|
||||
Look for: maintainer history, issue tracker activity, no suspicious install scripts
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "verified" once you've confirmed all packages are legitimate</resume-signal>
|
||||
</task>
|
||||
```
|
||||
|
||||
**During execution** — if an install fails, the executor surfaces a checkpoint and stops. It does not silently try a similarly-named alternative (which could be even more dangerous).
|
||||
|
||||
#### Slopcheck verdicts
|
||||
|
||||
| Verdict | Meaning | GSD action |
|
||||
|---------|---------|------------|
|
||||
| `[OK]` | Package passes all legitimacy checks | Proceeds — no checkpoint added |
|
||||
| `[SUS]` | Suspicious signals (new, low downloads, no source repo, etc.) | Flagged in Audit table; planner adds `checkpoint:human-verify` before install |
|
||||
| `[SLOP]` | High-confidence hallucination or attacker-registered package | Removed from RESEARCH.md; never reaches planner |
|
||||
|
||||
#### Claim provenance and WebSearch packages
|
||||
|
||||
Package names discovered through WebSearch are always tagged `[ASSUMED]` in RESEARCH.md, regardless of whether `npm view` succeeds. A package that exists on the registry is not the same as a package that's safe to install — `npm view` only proves registration, not legitimacy.
|
||||
|
||||
`[ASSUMED]` packages trigger the same `checkpoint:human-verify` gate as `[SUS]` packages. You'll see the checkpoint with a link to the registry page and guidance on what to look for.
|
||||
|
||||
#### If slopcheck isn't installed
|
||||
|
||||
GSD attempts `pip install slopcheck` at research time. If that fails:
|
||||
|
||||
- Every recommended package is tagged `[ASSUMED]`
|
||||
- The planner gates every install with a `checkpoint:human-verify` task
|
||||
- Research and planning complete normally — nothing hard-fails
|
||||
|
||||
This is intentionally stricter than the normal flow: slopcheck unavailability means every package install gets a human checkpoint, which is the safest fallback.
|
||||
|
||||
To install slopcheck manually:
|
||||
|
||||
```bash
|
||||
pip install slopcheck
|
||||
# verify: slopcheck install express --json
|
||||
```
|
||||
|
||||
#### slopcheck dependency
|
||||
|
||||
`slopcheck` is a MIT-licensed Python tool maintained by ToxSec (the researcher who documented the slopsquatting attack surface). It checks packages across npm, PyPI, crates.io, RubyGems, Go modules, Maven, and Packagist using multi-signal heuristics: registry age, download count, source-repo linkage, naming distance to popular packages, and registry-specific suspicion patterns.
|
||||
|
||||
If `slopcheck` is ever unavailable or abandoned, GSD's `[ASSUMED]`-gate fallback ensures you always get a human checkpoint before any install — the system never silently degrades to the pre-v1.51 behavior.
|
||||
|
||||
---
|
||||
|
||||
### Execution Wave Coordination
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user