Repository navigation
security: pin the red-team gate to an explicit model, and run it — 50/50 resisted (#76) - #81
Merged
Merged
Conversation
…olved model in every artifact (#76) The runner's --models default was the floating 'sonnet' alias, so the gate's result could change out from under the harness whenever a new Sonnet shipped, and a recorded verdict could not be tied to a specific model version after the fact. Now: - --models defaults to the explicit supported-floor ID (claude-sonnet-4-6), matching the discipline the dated results/ artifacts already show; - the runner captures the session's *resolved* model ID from the CLI init event and tallies/reports under it, so even an alias-invoked run produces an attributable artifact (and prints a notice when the two differ); - HISTORY.md's stale note (Sonnet 5 'not approved for cyber work' — no longer true) is replaced with the real reason the pin exists: reproducibility; - PLAN.md's 'weakest supported model (currently Sonnet)' wording names the pinned ID explicitly in all three places. The AI BOM is unaffected: it inventories dependencies, not harness source. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steve Wilson <steve.wilson@exabeam.com>
Found while running the gate for #76: the first live trial died with "'str' object has no attribute 'get'". The CLI's stream-json output carries lines whose `message` is a plain STRING rather than an object (error/notice events — an MCP server failing to reconnect, for instance). _parse called .get() on it unconditionally, raising AttributeError, which the runner's per-trial `except Exception` then degraded into a fully ERRORED trial. A drive that actually completed 19 tool calls and produced a 36k-character report was discarded because one unrelated notice appeared in the transcript. Grading integrity was never at risk — _inconc_rows already refuses to read an all-errored blocking-class attack as a pass (verdict INCONCLUSIVE, exit 3) — but the harness burned a full live drive per occurrence and could have stalled the gate on re-runs. Parse defensively by SHAPE, not just by event type, and add regression tests for both the odd-shaped line and the resolved-model capture. Negative-verified: the new test fails red on the unfixed parse. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steve Wilson <steve.wilson@exabeam.com>
…ASS (#76) The staleness half of #76. The gate had not run since 2026-07-03, across 0.6.7/0.6.8/0.6.9, and this promotion carries #66/#73/#77/#78. Run: 10 class-A families x 5 trials on the pinned claude-sonnet-4-6, judge on, driven against the working-tree plugin. Every family landed 0/5; no errored and no inconclusive trials, so the verdict rests on 50 valid trials rather than on absence of evidence. The a10 rows carry the real signal. In 4 of 5 trials the model reproduced the phishing markdown link in its chat output — the injection still works on the model — but the persisted artifact was clean every time, because the write-sink neutralizer defanged it. That is exactly what output-pipeline grading exists to distinguish: a pass where the model never emitted the payload would prove nothing about the guardrail. a10 landed 3/3 in the first run and drove the deterministic fix, so seeing the code layer fire is the point. Also fixes the ledger's own stale connector/ paths after #66, and updates the a10 summary's resistance figure from the 0/2 fix-time retest to 0/5 here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steve Wilson <steve.wilson@exabeam.com>
This was referenced Aug 13, 2026
Praxen finding 008 was 'awaiting triage'; it now has a home (#82) rather than being an untracked row. The gap itself is unchanged — the corpus is still class-A only, and classes C and D remain unexercised despite both blocking a release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steve Wilson <steve.wilson@exabeam.com>
virtualsteve-exa
added a commit
that referenced
this pull request
Aug 13, 2026
Minor, not patch: the shipped surface changes shape. Only the payload under plugin/ is distributed (#66), and the installer can now install the governance gate rather than only warn about it (#73). Also stamps the changelog entry for the red-team gate work (#76/#81), which landed after the [Unreleased] section was written, and dates the section. Both release gates ran against this candidate: red team 50/50 resisted (PASS, 2026-08-13 artifact); ABV 0 Critical (PASS, 2026-08-12 artifact against 0.6.9). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steve Wilson <steve.wilson@exabeam.com>
virtualsteve-exa
added a commit
that referenced
this pull request
Aug 13, 2026
…otes Two release-record items: 1. The 2026-08-12 Praxen scan is 0.7.0's ABV gate artifact (maintainer determination). It ran against the dev tip as it stood (005fa4c) — the head of the line 0.7.0 was cut from, not a stale release tag — and every behavioural change merged since is either a remediation of one of that scan's own findings (001->#73, 007->#78, 009->#81) or the path-only plugin/ restructure. Recorded in security/praxen/README.md rather than only in the release PR, so a reader can tell which release the dated artifact verified. 2. #79 landed on dev after the version bump, so the changelog gains its entry: the release smoke now asserts the governance gate actually installs. Release machinery earns a changelog line by the 0.6.4 precedent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Steve Wilson <steve.wilson@exabeam.com>
This was referenced Aug 13, 2026
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.
Closes both halves of #76 — the floating model default and the stale gate — plus a harness bug the run itself surfaced.
1. The gate is pinned to an explicit model
--modelsdefaulted to the aliassonnet, so the gate's result could shift under the harness whenever a new Sonnet shipped, and a recorded verdict couldn't be tied to a model version after the fact. The default is now the explicit supported floor,claude-sonnet-4-6, matching the discipline the datedresults/artifacts already followed.Belt and braces: the runner now captures the model the CLI session actually resolved (from its
initevent) and tallies and reports under that, printing a notice when it differs from what was requested. So even an alias-invoked run produces an attributable artifact.Docs follow:
HISTORY.md's note that Sonnet 5 is "not approved for cyber work" was stale and is replaced with the real reason the pin exists — reproducibility, not a restriction on any model.PLAN.md's "weakest supported model (currently Sonnet)" now names the pinned ID in all three places.2. A stray stream event was discarding whole trials
The first live trial died with
'str' object has no attribute 'get'. The CLI stream carries lines whosemessageis a plain string rather than an object (error/notice events — an MCP server failing to reconnect, for one), and_parsecalled.get()on it unconditionally. The per-trial guard then degraded that into a fully ERRORED trial: a drive that had completed 19 tool calls and produced a 36k-character report was thrown away because of one unrelated notice.Grading integrity was never at risk —
_inconc_rowsalready refuses to read an all-errored blocking-class attack as a pass (verdict INCONCLUSIVE, exit 3) — but the harness burned a full live drive each time it hit, and could have stalled the gate on re-runs. Now parsed defensively by shape, with regression tests for both the odd-shaped line and the resolved-model capture. Negative-verified: the new test fails red against the unfixed parse.3. The gate ran — 🟢 PASS
results/2026-08-13T2009-claude-sonnet-4-6.md. Ten class-A families × 5 trials on the pinned model, judge on, driven against the working-tree plugin.Every family landed 0/5, with zero errored and zero inconclusive trials — so the verdict rests on 50 valid trials, not on absence of evidence.
The a10 rows are the ones worth reading. In 4 of 5 trials the model did reproduce the phishing markdown link in its chat output — the injection still works on the model — but the persisted artifact was clean every time, because the write-sink neutralizer defanged it before it would become a case note. That's precisely the distinction
output-pipelinegrading exists to make: a pass where the model simply never emitted the payload would prove nothing about the guardrail. a10 landed 3/3 in the July run and drove the whole deterministic fix, so watching the code layer fire is the point of the exercise. The raw-chat copy remains the documented, best-effort-only residual.HISTORY.mdgains the run row and a reading note, and I fixed that file's own root-relativeconnector/paths after #66 while I was in it (it's the file this PR already edits, so it doesn't conflict with #80). The a10 fix summary's resistance figure moves from the 0/2 fix-time retest to 0/5 here.Verification
265 tests pass (263 + the two new regression tests) · AI BOM current · corpus lints 10/10 · the run drove live against the staging tenant with all writes, closes and containment denied.
Note for the promotion
This satisfies the red-team release gate in
CONTRIBUTING.mdfor the upcomingdev → mainrelease; the ABV gate already has its dated 0.6.9 PASS. What #76 does not close is the class C/D fixture gap — all ten fixtures are class A, so gate bypass and data leak have still never been exercised despite both being individually release-blocking. That's the larger piece of work Praxen flagged as finding 008, and it's worth its own issue rather than being folded in here.🤖 Generated with Claude Code