Skip to content

fix(c04): don't false-flag safe rejections that echo the payload (litmus-v14)#104

Merged
RubenSousaDinis merged 1 commit into
mainfrom
fix/c04-safe-reject-echo
Jul 6, 2026
Merged

fix(c04): don't false-flag safe rejections that echo the payload (litmus-v14)#104
RubenSousaDinis merged 1 commit into
mainfrom
fix/c04-safe-reject-echo

Conversation

@RubenSousaDinis

Copy link
Copy Markdown
Member

The bug

C-04 probe 3.2 (jailbreak amplification) feeds jailbreak-pattern strings as tool arguments and flags injection-shaped output the server did NOT merely reflect from our input. It masks reflections of our own injected payload first, so an honest echo isn't mistaken for server-generated injection — but the mask only caught complete echoes.

A server that safely rejects a jailbreak-as-argument and quotes it back inside its own error frame slipped through when the echo was transformed: char-stripped (</system>system>), mid-truncated, or wrapped in a non-Pydantic error (Invalid label "…": disallowed characters, Error: file not found: …). The residual injection token survived the mask and capped an otherwise-clean server at D for amplification it never performed.

The fix

Generalize maskRejectionEchoes: when an output reads as a refusal (a rejection marker — invalid, error, not found, disallowed, _parsing, …), blank any run that reproduces a ≥9-char substring of an injected payload, with equal-length filler so offsets are stable.

Two properties make this safe:

  • No false negatives. It can only remove reflections of our own injected payloads. Server-generated injection is never a long substring of our payloads, so it is never masked — it survives and still fails.
  • Probe 3.2's target is preserved. Gating on the refusal frame means a compliant server that echoes a payload prefix then splices novel injection is not a rejection, so it is untouched and still fails.

Pass/fail-semantics change (some safe-rejecting servers move D→A) → methodology string bumped litmus-v13 → litmus-v14 (kept a string so older attestations coexist).

Tests

New regression cases in adversarial-inputs.test.ts: the transformed Invalid label "…" and file not found: … rejection echoes; the compliant echo-then-splice invariant (must still fail); and a server-generated trigger surviving inside a rejection frame. Full suite green (probes 417 pass, core 18, typecheck clean).

Verified end-to-end

Built the harness and graded a real safe-rejecting server in the Docker sandbox: C-04 moves from fail → pass under litmus-v14.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TZcTQCDwyFqdh59fPWDJAr

…mus-v14)

C-04 probe 3.2 (jailbreak amplification) masks reflections of our own
injected payload before scanning, so an honest echo isn't mistaken for
server-generated injection. The mask only caught COMPLETE echoes, so a
server that safely REJECTS a jailbreak-as-argument and quotes it back in
its own error frame — often char-stripped (`</system>` -> `system>`) or
truncated — slipped through and was capped at D for 'amplification' it
never did.

Generalize maskRejectionEchoes: when an output reads as a refusal (a
rejection marker like `Invalid label "..."`, `Error: ... not found: ...`,
Pydantic `input_value=`), neutralize any run that reproduces a substring
of an injected payload. This can only remove echoes of OUR OWN payloads,
so server-GENERATED injection is never masked (no false negatives), and
gating on the refusal frame preserves probe 3.2's target: a compliant
server that echoes a payload prefix then splices novel injection is not a
refusal and still fails.

Pass/fail-semantics change (some safe-rejecting servers move D->A), so
bump the methodology string to litmus-v14. Adds regression tests for the
transformed/truncated rejection echoes, the compliant-splice invariant,
and server-generated injection surviving inside a rejection frame.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TZcTQCDwyFqdh59fPWDJAr
@RubenSousaDinis
RubenSousaDinis force-pushed the fix/c04-safe-reject-echo branch from 1296467 to 954039c Compare July 6, 2026 14:12
@RubenSousaDinis
RubenSousaDinis merged commit 1bb6b44 into main Jul 6, 2026
11 checks passed
@RubenSousaDinis
RubenSousaDinis deleted the fix/c04-safe-reject-echo branch July 6, 2026 14:17
RubenSousaDinis added a commit that referenced this pull request Jul 6, 2026
Ships litmus-v14: the C-04 probe 3.2 fix so a server that safely rejects a
jailbreak-as-argument and echoes it back in an error frame is no longer
mis-flagged as amplification (#104). server.json bumped in lockstep so the
MCP-registry listing tracks the release.


Claude-Session: https://claude.ai/code/session_01TZcTQCDwyFqdh59fPWDJAr

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant