dream(security-adversarial): mcp-scan missed Bash(python *) — live in vertical:ai (evaluated) - #210
Draft
ruvnet wants to merge 1 commit into
Draft
dream(security-adversarial): mcp-scan missed Bash(python *) — live in vertical:ai (evaluated)#210ruvnet wants to merge 1 commit into
ruvnet wants to merge 1 commit into
Conversation
…e) + unrestricted Bash(*) (evaluated) harness mcp-scan's risky-bash-allow regex omitted arbitrary-code interpreters (python/node/ruby/perl/bash/sh) - the vertical:ai template's own settings.json.tmpl ships Bash(python *), unflagged by any check until now. Also adds a new unrestricted-bash-allow HIGH finding for bare Bash/Bash(*), disclosed as defense-in-depth rather than a live generator bug after an independent critic traced the call graph and found no shipped generator currently writes that exact string to .claude/settings.json. Evidence: real (non-synthetic) `metaharness --template vertical:ai` scaffold repro plus a deterministic before/after stash repro; 15/15 mcp-scan tests, 457/457 full package suite, 0 regressions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R1diHYv256aiVNdEEUMfjG
This was referenced Aug 19, 2026
Draft
This was referenced Aug 27, 2026
ruvnet
pushed a commit
that referenced
this pull request
Sep 1, 2026
…edger conflict Main advanced again (5b4ebd3 -> 1ded6f2): #212 (github-actions shell/YAML injection fix, another backlog item flagged in issue #257) merged, plus a published-smoke CI gating fix (#263). Real conflict again in docs/dream-cycle/LEDGER.md: main's real #212 row replaced this branch's stale "OPEN (backfilled)" placeholder for the same PR. Resolved by taking main's real #212 row (with its actual receipt/ witness) and updating every row that referenced #212 as still-open to note its 2026-09-01 merge, narrowing tonight's own row's still-OPEN list accordingly (now just #207 and #210). Re-validated: full monorepo build clean; packages/flywheel 72/72; all 7 real committed ReplayBundle/proof-bundle files still verify PASS; flywheel + host-github-actions + create-agent-harness + web-ui — 558/560 (2 pre-existing skips) green, 0 failures. CI's earlier packages/avo/rvf-resume.test.ts flake also confirmed non-recurring on the previous head — not re-checked here as it's unrelated to this merge. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012NE5wk64pND2VpBZmGGkQq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MetaHarness Dream Cycle, 2026-08-18. Deep surface:
security-adversarial(slot 3). Full detail, receipts, candidate-selection reasoning, adversarial-critique writeup, and sbom/policy scan findings: #209.Hypothesis
Given
scanMcp's host-permission-check loop, which flags only exact wildcard strings (*,mcp__*,mcp__*__*) and a regex over a fixed binary list (rm|curl|wget|sudo|chmod|ssh), when the regex's binary alternation is extended to include arbitrary-code interpreters (python,python3,node,ruby,perl,bash,sh) and a new exact-match branch flags fully unscopedBash/Bash(*)as a separate HIGH finding, then a realmetaharness --template vertical:aiscaffold's shippedBash(python *)allow-rule should be flaggedrisky-bash-allow(MEDIUM) where it previously scanned clean, subject to: (a) zero regression in the package's 455-test baseline, (b) no existing test modified, (c) the new checks must not false-positive on narrower, legitimately-scopedBash(...)rules, (d) diff materially under 300 lines.Candidate
packages/create-agent-harness/src/mcp-scan.ts's host-permission-check loop gained: (1) an exact-match branch forBash/Bash(*)→ newunrestricted-bash-allowHIGH finding; (2) the existingrisky-bash-allowregex's binary alternation extended withpython3?|node|ruby|perl|bash|sh. 2 source files (mcp-scan.ts+9/-2), 1 test file (+38 lines, 5 new tests). 44 lines net — well under the 300-line target.Evaluation Receipt
metaharness --template vertical:ai --host claude-code— producing a real.claude/settings.jsoncontaining"Bash(python *)".harness mcp-scanagainst that output: before fix, 2 findings (no-policyHIGH,unpinned-depsLOW), python grant invisible; after fix, 3 findings, adding[MED] Risky shell allow-rule: Bash(python *). Byte-identical CLI invocation, only the scanner code differed.src/mcp-scan.tsreverted (tests kept), the 5 new tests fail exactly as predicted; the 10 pre-existing tests are unaffected.packages/create-agent-harness457 passed, 2 skipped (baseline 455/2, 0 regressions),tsc --noEmitclean, full monorepo build clean (no wasm/NAPI degradation tonight).Bash(*)doesn't double-fire the narrowerrisky-bash-allowid; scoped rules (Bash(npx foo*),Bash(git *)) remain unflagged.Baseline Comparison
@metaharness/agntcy(the one dependent package that structurally readsmcp-scan'sFinding[]shape, per its ownfrom-mcp-scan.tsdocstring) re-run clean (1/1) — its badge-derivation logic only mapsallow-shell/allow-network/allow-file-writeids to badges and deliberately treats other ids (including the two new ones) as risk findings, not badges, matching existing design intent.Darwin Lineage
Not run — this is a static-analysis coverage fix to a CLI scanner (fixed regex/exact-match check), not a tunable routing/topology/prompt/tool/tier parameter; no Darwin mutation surface applies (ADR-071 allowlist), same reasoning as the 2026-08-16/17 entries.
Flywheel Evidence
Not applicable in the "ran a flywheel evolution" sense — this candidate hardens
@metaharness/create-agent-harness's own static scanner. Durable evidence is the real-CLI + deterministic repro above, committed todocs/dream-cycle/2026-08-18-gist.md.Reward Hack Check
Purely additive diff — no existing test, fixture, or gold data touched (confirmed independently by the adversarial critic re-reading the diff hunks). No threshold changed, no metric substituted.
mcp-scanremains pure/read-only, unchanged tonight.Security Review
This is the security-review surface tonight. Also checked and clear: no other
.claude/settings.json.tmpltemplate ships an unscoped shell/interpreter allow-rule (vertical_aiwas the only offender);redact.ts/secrets.tsuntouched; no new dependency or credential/network surface added.Regression Analysis
Zero regression: 457/457
packages/create-agent-harnesstests pass (0 failures, 2 pre-existing skips unaffected),tscand full repo build clean, dependent-package test unaffected (1/1).ADR
Appended a dated 2026-08-18 section to
ADR-022(the ADR that documentsmcp-scan's checks) rather than minting a new ADR number, matching the 2026-08-13/14/17 precedent for a coverage/completion addition to an existing architectural decision.Research Gist
No gist-creation tool is available in this session's toolset (matching 2026-08-13 through 08-17) — committed instead:
docs/dream-cycle/2026-08-18-gist.md(GIST=LOCAL).Issue
#209 (full findings, candidate-selection reasoning, adversarial-critique writeup including a self-caught overstatement correction, sbom/policy scan results, competitor review, ledger check/backfill).
Witness
Verifier procedure is in the gist's Witness section and was independently self-verified (round-trip reproduced programmatically) before this PR was opened.
Merge Policy
Human review required. Do not self-merge. Do not autonomously promote Flywheel state.
Recommendation: ACCEPT-WITH-CAVEATS — small, dual-repro'd (real CLI + deterministic unit) fix to a genuinely live gap in the repo's own security scanner. One disclosed correction along the way: the initial draft overstated the
Bash(*)/bare-Bashhalf as traceable to a live generator bug athost-config.ts:45; an independent critic traced the real call graph, found that path unreachable through any shipped generator today, and the framing was corrected before this PR opened — that half ships as disclosed defense-in-depth, not as a second live-vulnerability claim. Two comparable-class gaps in sibling tools are disclosed as open next steps, not silently fixed under scope pressure: (1)threat-modelnever consultsmcp-scan's findings, so the same harness can be HIGH on one tool and "clean" on the other; (2)harness sbomhas no Cargo/Rust awareness despite--with-wasmlegitimately shipping Rust deps in scaffolded harnesses.Generated by Claude Code