Skip to content

security-adversarial: BASELINE_COMMIT git-show oracle fails opaquely on a shallow clone (issue #149) - #150

Merged
ruvnet merged 6 commits into
mainfrom
dream/2026-10-03-security-adversarial
Nov 6, 2026
Merged

ruvnet merged 6 commits into
mainfrom
dream/2026-10-03-security-adversarial

Conversation

@ruvnet

@ruvnet ruvnet commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Closes #149.

Hypothesis

Given a git checkout whose local history does not reach the hardcoded BASELINE_COMMIT (35c9fd31ec0369f1c4b0ac7d5eda13d766bbb8cf) that scripts/benchmark-ticket-codec.mjs's withReference() fetches via git show <sha>:<path> — the realistic case for a shallow clone (reproduced live on this session's own fresh checkout) — adding a self-heal step (git fetch --depth 1 origin <BASELINE_COMMIT>, the literal constant only, never a caller-supplied ref) before the existing git show should make the previously-failing governance tests pass with network access to origin, and produce a clear, actionable diagnostic instead of an opaque stderr dump without it — without ever making BASELINE_COMMIT configurable. Confirmed.

Candidate

scripts/benchmark-ticket-codec.mjs: adds hasCommit(commit) (exported, git cat-file -e <commit>^{commit}, stderr silenced) and tryFetchCommit(commit) (private, git fetch --depth 1 origin <commit>, best-effort). withReference() now checks hasCommit(BASELINE_COMMIT) first; if missing, attempts the fetch, then asserts again with a clear message naming the remediation (git fetch --depth 1 origin <sha> or fetch-depth: 0, citing .github/workflows/ci.yml's existing precedent) if it still can't resolve. BASELINE_COMMIT itself is unchanged — still a hardcoded literal, never configurable; the golden comparison logic (git show, hashing, transpile, differential compare) is untouched.

scripts/benchmark-ticket-codec.test.mjs: +2 tests — one confirming hasCommit(BASELINE_COMMIT) is true after withReference()'s self-heal runs (regression guard that the pinned commit stays resolvable), one confirming hasCommit('0'.repeat(40)) is false (a syntactically valid, never-existing object id — exercises the negative/missing-commit branch deterministically, without depending on real network failure to prove it).

+32/-0 net new lines in the source file, +14 in the test file. Well under the 300-line target, one conceptual change.

Evaluation Receipt

Real evaluator: npm test (vitest run && npm run test:governance), run live before and after on this session's own shallow checkout (candidate stashed for the baseline run, then restored):

vitest governance
Parent (baseline) 769 passed 150 run, 147 pass / 3 fail
Candidate 769 passed (unchanged) 152 run (+2 new), 152 pass / 0 fail

npm run typecheck and npm run lint clean on the candidate.

Baseline

Measured live by git stash-ing the candidate diff and re-running the identical node --test scripts/benchmark-ticket-codec.test.mjs / npm test commands — not inferred from logs, not simulated.

Darwin Lineage

DARWIN=blocked. npx @metaharness/darwin --version responded (entrypoint live), but this session's own sandbox permission classifier denied the bounded evolve invocation as "Code from External"; not worked around. Corroborates the repo's already-tracked evaluatorEntrypoints.darwin unpinned-npx finding (packages/compile/src/supplychain.ts). Not required for this verdict (Darwin is optional, "only if available" — judged not safely available tonight).

Evidence

OBSERVATION (live 3-test baseline failure) → OBSERVATION (git cat-file -e confirms missing object) → OBSERVATION (CI's own fetch-depth: 0 precedent) → HYPOTHESIS (frozen above) → MEASUREMENT (769/150→147 baseline; 769/152→152 candidate) → INFERENCE (independent critic, separate context) → DECISION (ship; ACCEPT).

Reward-Hack Check

Independent adversarial critic (separate subagent, no authorship stake, read the real diff and live .git state directly, not a paraphrase): CLEAR. No fixture/golden-answer/threshold/seed/iteration-count touched. Confirmed content-addressing holds (a git fetch of an exact SHA cannot be redirected to different content without a hash collision). Confirmed no masking of a real reference/candidate mismatch — the comparison logic runs unchanged once the commit resolves. Confirmed the new error message's CI-precedent file/line references are accurate. One nitpick adopted (silence git cat-file -e's stderr on a miss); non-blocking notes on .git side-effect visibility left as disclosed, not blocking.

Security Review

No prompt-injection/MCP-authority/credential surface touched. Filesystem scope: only new side effect is git fetch --depth 1 origin <fixed-sha>, writing objects/refs into this checkout's own .git — content-addressed, so the fetched bytes are cryptographically bound to the already-hardcoded SHA; nothing lets a caller substitute a different commit. Network scope: outbound to origin only. No production/runtime code path changed.

Regression Analysis

0 regressions: vitest count unchanged (769), governance count increased only by the 2 new tests added here, all previously-passing tests still pass. The 3 newly-passing tests were never weakened — they are the exact same assertions, now reached for the first time on this checkout.

ADR

None. Not an architectural decision — a reliability/reproducibility fix to test infrastructure, explicitly out of scope per STEP 19 ("never for parameter changes... minor... tweaks").

Gist

GIST=LOCAL — no gh CLI (invalid token this session) or gist-creation MCP tool available. Full report committed at docs/dream-cycle/2026-10-03-security-adversarial-report.md.

Issue

#149

Witness

report_sha256 : ae3f612f711f83ee1035e49c6d5c03808b291a82bab03189e7239c5edf5a5522
session_commit: 23a577082aad39750051dc7ef0ec9d0d72900adf
witness       : 3c3dc0728d1b327253b66d0021e80ffd0d5084056644f7f424baf31206ba416f

Reproduce: node packages/cli/dist/bin.js witness verify-report docs/dream-cycle/2026-10-03-security-adversarial-report.md --commit 23a577082aad39750051dc7ef0ec9d0d72900adf

Merge Policy

Human review required. This session never self-merges and never autonomously promotes candidate state. No automerge-safe label applied.


🤖 Generated with Claude Code

https://claude.ai/code/session_01NNkaaVC27NoJSbhxb782x5


Generated by Claude Code

claude added 2 commits October 3, 2026 09:28
…on a shallow clone (issue #149)

scripts/benchmark-ticket-codec.mjs's withReference() hardcodes BASELINE_COMMIT
and fetches a reviewed historical reference via `git show <sha>:<path>`,
deliberately refusing any arbitrary revision argument. On a shallow clone
that doesn't reach that commit (reproduced live on this session's own fresh
checkout), the 3 "pinned reviewed reference" governance tests failed with a
bare execFileSync stderr dump instead of a diagnosis. This repo's own CI
already works around the identical fragility with `fetch-depth: 0`
(.github/workflows/ci.yml, dream-nightly.yml) but no other checkout path is
protected.

Adds hasCommit()/tryFetchCommit(): before the existing git show, self-heal
by fetching exactly the hardcoded BASELINE_COMMIT literal (never a
caller-supplied ref, so the "no arbitrary revision" property is unchanged)
with `git fetch --depth 1 origin <sha>`; if that still doesn't resolve,
raise a clear, actionable error instead of the opaque one. Content-addressed
fetch of a fixed SHA cannot be redirected to different content.

npm test 769+150->769+152 (+2 new regression tests), 3 previously-failing
governance tests now pass, 0 regressions elsewhere. typecheck/lint clean.
Independent adversarial critic (separate subagent context): CLEAR, no
reward-hacking or security weakening; one nitpick (silence git cat-file -e's
stderr) adopted. Darwin: blocked by this session's own sandbox policy
(unpinned external code), corroborating the already-tracked
evaluatorEntrypoints.darwin finding.

Report: docs/dream-cycle/2026-10-03-security-adversarial-report.md
Witness: 3c3dc0728d1b327253b66d0021e80ffd0d5084056644f7f424baf31206ba416f

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NNkaaVC27NoJSbhxb782x5
…heal

Ledger row for 2026-10-03: issue #149, PR #150, ACCEPT, witness 3c3dc072.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NNkaaVC27NoJSbhxb782x5
This was referenced Oct 5, 2026
This was referenced Oct 12, 2026
# Conflicts:
#	docs/dream-cycle/LEDGER.md
…fc3222

Merged main into this draft (merge commit 7807661, no rebase/force-push),
re-ran the real evaluator and a fresh independent critic/reward-hack pass
on the unchanged diff, refreshed the report's Evaluation Receipt and
Witness. ACCEPT still holds; stays draft because dependency-audit is red
on this head for a pre-existing, unrelated reason (issue #197).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aoR1LqtwDHBLDLMWxRcUa

ruvnet commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

Dream Cycle consolidation — 2026-10-24

MODE=CONSOLIDATE (STEP 1.5): 20 open dream/* candidate PRs tonight, well over implementationTrack.reviewBacklogLimit=6. The two nearer-the-front eligible drafts, #145 and #148, already carry a dream-consolidate marker for today's exact default-branch SHA (3fc3222) from the two preceding nights. This PR was the oldest still-eligible draft (still draft, ACCEPT in its own Evaluation Receipt, not a routine-self-review PR) carrying no prior consolidate marker at all.

Action. Merged main (3fc3222d2e5566a203331d3686c4d2eaf06713a8) into this branch with an ordinary merge commit (7807661, never rebase/force-push). One textual conflict in docs/dream-cycle/LEDGER.md (both sides had appended rows since this branch's 2026-10-03 base) — resolved by chronological concatenation, no row lost either side. scripts/benchmark-ticket-codec.{mjs,test.mjs} (this candidate's only files) auto-merged clean with no competing change on main since baseline — confirmed git diff 8fe3b8a..HEAD -- scripts/benchmark-ticket-codec.mjs scripts/benchmark-ticket-codec.test.mjs is empty, so the diff under review is byte-identical to the original round's.

Re-evaluation on the new head. Real evaluator (npm test): vitest 886/886 (matches main's own baseline on this exact head), governance 197/197 (+2, this candidate's own tests over main's 195/195 baseline), 0 regressions. npm run typecheck/npm run lint clean. node packages/cli/dist/bin.js ledger verify --path docs/dream-cycle/LEDGER.md --since-row 38 --legacy-digest 23b02bfa98b56b374fadfb1b05df25e589dcdeab26143ae6183083d21779426a (the exact CI gate): OK, 55 rows.

Fresh critic + reward-hack pass (this round, independently re-derived from the live diff, not a reread of the prior verdict). Confirmed tryFetchCommit is called only with the hardcoded BASELINE_COMMIT literal (no caller-supplied ref anywhere). Ran a live negative control: swapped in the pre-candidate file version, confirmed the governance test file fails outright (missing hasCommit export) rather than passing vacuously, then restored the exact candidate bytes and confirmed git status/git diff showed nothing residual. Ran scripts/benchmark-ticket-codec.test.mjs in isolation: 5/5 pass (3 original + 2 new). No gold answer, threshold, seed, or iteration count touched; no file outside the two named is touched. Security surface unchanged: git fetch --depth 1 origin <fixed-sha> is content-addressed to an already-hardcoded literal, fetched from origin only. CLEAR.

CI on the pushed head. test (both Node versions), software-evidence, dependency-security, no-optional-deps, guard, CodeQL are green. Red: dependency-audit (npm audit --audit-level=high) — reproduced locally against this exact head's lockfile; git diff origin/main -- package-lock.json from this branch is empty, so the lockfile is byte-identical to main's. Same pre-existing, already-tracked vite/launch-editor dev-toolchain advisory as issue #197 (opened 2026-10-21, still open, no fix PR exists to port — a semver-range-breaking vite bump is out of scope for this single-function test-infrastructure fix). Not re-filing a duplicate issue; not fixing it from this PR.

Decision. ACCEPT still holds and the fresh critic is clear, but not every required check on the new head is green (dependency-audit, for the reason above) — per STEP 1.5, this PR stays draft. Report refreshed at docs/dream-cycle/2026-10-03-security-adversarial-report.md with a new Evaluation Receipt and witness (e4b8f464…, self-verified via dream-machine witness verify-report). Ledger row appended: docs/dream-cycle/LEDGER.md (2026-10-24).

No merge, no close, no force-push, no self-promotion.


Generated by Claude Code


Generated by Claude Code

…cted)

Intent/result receipts for tonight's external side effects (1 push, 1 PR
comment, 1 issue comment) per the schedule contract (ruvnet/core-memory
AGENTS.md rule 5, issue #187). Reconstructed after the fact from this
session's own tool-call record, same as the 2026-10-21 precedent.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aoR1LqtwDHBLDLMWxRcUa
@ruvnet
ruvnet marked this pull request as ready for review November 6, 2026 14:27
@ruvnet
ruvnet merged commit 70d7059 into main Nov 6, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants