Skip to content

security-adversarial: gate CI on npm audit production findings (issue #43) - #46

Draft
ruvnet wants to merge 2 commits into
mainfrom
dream/2026-08-28-security-adversarial
Draft

security-adversarial: gate CI on npm audit production findings (issue #43)#46
ruvnet wants to merge 2 commits into
mainfrom
dream/2026-08-28-security-adversarial

Conversation

@ruvnet

@ruvnet ruvnet commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Nightly Dream Cycle, 2026-08-28. DEEP=security-adversarial, SCAN=redblue,supply-chain. Full report: docs/dream-cycle/2026-08-28-security-adversarial-report.md. Issue: #45.

Hypothesis

Given this repo's CI pipeline, which currently reports npm audit findings without gating on them, when a deterministic classifier is added that parses npm audit --omit=dev --json output and fails CI only on a high/critical finding within that production-scoped report, then CI should correctly distinguish reachable production risk from dev-toolchain risk — subject to: no existing test modified/weakened, no re-derivation of npm's own dependency-graph reachability computation, zero-false-negative against a synthetic high/critical finding, zero-false-positive against tonight's real dev-only findings. Frozen before implementation.

Candidate

+373/-0 across 6 files (2 new source files, 1 new report, 3 small edits: CLI wiring, CLI tests, CI workflow). One conceptual change: packages/cli/src/auditgate.ts (pure classifyAuditGate()) wired into a new dream-machine audit-gate CLI command and a new dependency-security CI job.

Evaluation Receipt

Real evaluator: npm test (vitest, this repo's own bench entrypoint).

Baseline (parent 7933c359) Candidate
Tests 98 111 (+13, 0 removed/modified)
Result 98 passed 111 passed
Lint clean
Build clean (all 6 packages)

Live end-to-end receipt (real repo data):

$ npm audit --omit=dev --json > /tmp/audit-prod.json
$ node packages/cli/dist/bin.js audit-gate --path /tmp/audit-prod.json
audit-gate: clear — 0 findings at any severity (critical=0 high=0 moderate=0 low=0)
exit code: 0

$ node packages/cli/dist/bin.js audit-gate --path /tmp/audit-full.json   # dev-inclusive, same night
audit-gate: blocked — 2 critical + 1 high finding(s) in this audit scope (critical=2 high=1 moderate=3 low=2)
exit code: 1

The second call proves the gate is not a rubber stamp — CI itself only ever points it at the --omit=dev report.

Baseline

Parent commit 7933c3599abe22df5290f4609d1f93f598feb3de, 98/98 tests passing, clean build.

Darwin Lineage

Not run — DARWIN=not-applicable. Probed live tonight (npx @metaharness/darwin evolve --sandbox mock → real leaderboard, winner g2_v5, delta +0.110, LIVE), but no evolvable population exists for a single, already-minimal pure classifier with one fixed policy boundary — same rationale as 2026-08-13/ADR-0002 and 2026-08-18/PR #19.

Evidence

Reproduced live tonight (grade A, first-hand): npm audit --omit=dev --json on this repo's real lockfile → metadata.vulnerabilities all-zero, metadata.dependencies.prod: 13. npm audit --json (dev-inclusive) → 2 critical, 1 high, 3 moderate, 2 low — matches issue #37's independently-reported findings exactly (GHSA-5xrq-8626-4rwp critical Vitest UI arbitrary file read, GHSA-fx2h-pf6j-xcff high Vite server.fs.deny bypass, plus esbuild/eslint-plugin-kit moderate/low). Full evidence trail with grades in the committed report.

Reward-Hack Check

Self-adversarial (solo session, no separate critic agent available):

  • Does not touch any existing test, gold answer, threshold, or the bench/darwin evaluator entrypoints.
  • Delegates production-reachability classification to npm's own --omit=dev dependency-graph walk rather than re-deriving it — avoiding exactly the false-positive/negative class of bug PR security-adversarial: detect unpinned npx supply-chain risk in evaluator entrypoints #19's independent critic caught in a hand-rolled npx-pinning detector on 2026-08-18.
  • Malformed/partial input (missing severity counts, non-audit JSON, npm error payloads) classifies as malformed (exit 2), never silently clear (exit 0) — dedicated tests for empty object, null/undefined, non-audit shape, and partial-counts shape.
  • CI's npm audit --omit=dev --json ... || true only survives npm audit's own nonzero exit on any finding; the gate command itself determines the job's real (non-rubber-stamped) exit code.
  • Boundary cases (single high with all else 0, single critical with all else 0, moderate/low-only) independently tested to block or clear correctly.

Security Review

No prompt-injection surface (pure JSON parsing, no LLM calls). No credential exposure, no new network I/O. New filesystem I/O is a single local read of a caller-supplied JSON path (io.readFile), consistent with every other CLI command's I/O surface. No change to io.exec's actual shell-exec path.

Regression Analysis

0 pre-existing tests modified or removed. All 98 baseline tests still pass unchanged; 13 new tests added (9 pure-classifier + 4 CLI-dispatch).

ADR

None. This extends ADR-0002's "classify, don't silently trust or silently fix" precedent within the existing architecture (a new CI job gating on an existing classification primitive), rather than introducing a new invariant.

Gist

No gh CLI or gist-creation tool available this session (same as 2026-08-13/2026-08-18). Report committed at docs/dream-cycle/2026-08-28-security-adversarial-report.md. GIST=LOCAL.

Issue

#45

Witness

report_sha256 : 409d5fc4902ebdaec272ee495583a56cd95cc18b2077097c82daa3e4045bdc9e
session_commit: 7933c3599abe22df5290f4609d1f93f598feb3de
witness       : fe3d8a92497e59700481b6ce27ba5fec39804c7f61fa18f7f6e2a3a52d7d3caa

Verify: sha256sum docs/dream-cycle/2026-08-28-security-adversarial-report.md, then printf '%s%s' "<that hash>" "7933c3599abe22df5290f4609d1f93f598feb3de" | sha256sum must equal the witness above. Confirmed tonight via dream-machine witness verify (✓ VALID).

Merge Policy

Draft — human review required. This PR does not carry the automerge-safe label: it adds a new CI job (gate infrastructure), which the repo's own merge policy treats as human-review-only regardless of risk level. The session never merges and never applies that label itself.


Generated by Claude Code

claude added 2 commits August 28, 2026 09:17
…43)

Nightly Dream Cycle, 2026-08-28. DEEP=security-adversarial, SCAN=redblue,supply-chain.

npm ci reports 8 dependency vulnerabilities (2 critical, 1 high, 3 moderate,
2 low) but CI does not gate on any of them (issue #43). `npm audit --omit=dev`
confirms live tonight that all 8 live in the vitest/vite/esbuild/eslint dev
toolchain — 0 of the 13 production dependencies are implicated.

Adds a deterministic classifyAuditGate() + `dream-machine audit-gate` CLI
command + a new CI job that fails only on a reachable high/critical
*production* finding (npm audit --omit=dev), and reports (never fails) on
dev-only findings. Delegates production-reachability classification to npm's
own dependency-graph walk rather than re-deriving it, avoiding the
false-positive/negative class of bug PR #19's critic caught in a hand-rolled
detector.

npm test: 98 -> 111 (+13, 0 removed/modified). Full report:
docs/dream-cycle/2026-08-28-security-adversarial-report.md
#46)

ACCEPT — audit-gate CI job scoped to npm audit --omit=dev, npm test 98->111, 0 regressions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants