Skip to content

fix(c01): stop injection false positives on placeholders, format examples, and zero-width doc artifacts (litmus-v13)#101

Merged
RubenSousaDinis merged 1 commit into
mainfrom
fix/c01-injection-fp-litmus-v13
Jul 6, 2026
Merged

fix(c01): stop injection false positives on placeholders, format examples, and zero-width doc artifacts (litmus-v13)#101
RubenSousaDinis merged 1 commit into
mainfrom
fix/c01-injection-fp-litmus-v13

Conversation

@RubenSousaDinis

Copy link
Copy Markdown
Member

What

The C-01 tool-output-injection scanner floored several honest MCP servers on benign structures rather than genuine hijacks. This tightens the detector so those cases pass while keeping true-positive detection intact, and bumps the methodology to litmus-v13.

False positives fixed

Pattern Example Was Now
Angle-bracket placeholder in usage text call_tool({ name: "<tool>" }) F A
Pipe-separated CLI placeholder target=<system | client | /group/> F A
XML data example <user><name>John</name>... F A
data: format description data:image/...;base64,..., data:{jsx:...} F A
Field label New system prompt (schema description) F A
Zero-width char in relayed docs U+200B bracketing an inline-code span F A

How

  • Role tags: strong <system>/<assistant> tags exclude | (a pipe placeholder isn't a role tag); weak <user>/<tool> tags must wrap a word character to count as an injected block.
  • data: URIs: flag only a real type/subtype mediatype URI, not a data:-prefixed description. data:text/html, SVG, and every javascript: URI still flag.
  • "new/updated system prompt": floors only as a colon-introduced directive (New instructions: ...), not as a bare field label.
  • Zero-width chars → normalize-then-scan (the important one): a zero-width code point is graded MEDIUM (recorded as evidence, not an automatic floor), because on its own it carries no instruction and is rampant as a benign documentation artifact. Keyword-evasion stays covered because the injection scanners now strip invisible code points before matching — so a zero-width-split keyword (ins<U+200B>tructions) de-obfuscates and still fails HIGH. Bidi/override and Unicode tag characters remain HIGH. Skill grading keeps every invisible char at the fail bar.

Methodology

Bumps METHODOLOGY_VERSION to litmus-v13 — a genuine C-01 pass/fail-semantics change. The field stays a string so older attestations coexist.

Verification

  • Full probes suite green (413 passed). The evil / injecting / second-order demo fixtures still grade F — true-positive detection is unchanged.
  • Seven real servers that previously mis-graded F now grade A under litmus-v13: @jshookmcp/jshook, @liangshanli/mcp-server-apidebug, ai-diagram-maker-mcp, arc-1, genable-mcp, mcp-vapi, pinescript-mcp-server.

…ples, and zero-width doc artifacts (litmus-v13)

The tool-output-injection scanner (C-01) floored several honest servers on
benign structures rather than genuine hijacks:

- Angle-bracket placeholders in usage text — a `<tool>` in a call_tool example,
  a `<system | client | /group/>` pipe-separated CLI placeholder — read as
  injected role tags.
- Data/format examples — a `<user><name>...` XML sample, `data:image/...;base64,...`
  and `data:{jsx:...}` format descriptions — read as role tags or script URIs.
- A "New system prompt" field label read as an injected directive.
- Zero-width code points that are ordinary artifacts of relayed upstream
  documentation floored C-01/C-04 outright.

Fixes:
- Strong `<system>`/`<assistant>` tags exclude `|`, so a pipe placeholder is not
  a role tag; weak `<user>`/`<tool>` tags must wrap a word character to count as
  an injected block.
- `data:` flags only a real mediatype URI, not a `data:`-prefixed description.
- "new/updated system prompt" floors only as a colon-introduced directive.
- A zero-width char is graded MEDIUM (recorded as evidence, not an automatic
  floor). To keep keyword-evasion covered, the injection scanners now strip
  invisible code points before matching, so a zero-width-split keyword
  (`ins<U+200B>tructions`) de-obfuscates and still fails HIGH. Bidi/override and
  Unicode tag characters stay HIGH. Skill grading keeps every invisible char at
  the fail bar.

Bumps methodology to litmus-v13 (a C-01 pass/fail-semantics change). True-positive
detection is unchanged — the evil/injecting/second-order fixtures still grade F.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNVwNaGUkogBKTtx5KK7X5
@RubenSousaDinis
RubenSousaDinis merged commit b9bb52f into main Jul 6, 2026
11 checks passed
@RubenSousaDinis
RubenSousaDinis deleted the fix/c01-injection-fp-litmus-v13 branch July 6, 2026 09:03
RubenSousaDinis added a commit that referenced this pull request Jul 6, 2026
Ships the litmus-v13 C-01 recalibration merged in #101: injection false
positives on angle-bracket placeholders, data:/format examples, and
zero-width doc artifacts no longer flip honest servers to F. Bumps the
package + server.json manifest versions to match the tag.


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

Co-authored-by: Claude Opus 4.8 (1M context) <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