Skip to content

feat(core): scrub leaked tool-call wire-format at the capture boundary - #63

Open
widgetii wants to merge 2 commits into
LamantinAI:mainfrom
widgetii:feat/sanitize-tool-call-scrub
Open

feat(core): scrub leaked tool-call wire-format at the capture boundary#63
widgetii wants to merge 2 commits into
LamantinAI:mainfrom
widgetii:feat/sanitize-tool-call-scrub

Conversation

@widgetii

Copy link
Copy Markdown
Collaborator

Problem

kaeru is an MCP server; its callers are arbitrary LLMs and it has no
control over how a model formats a tool call. A malformed call can spill
the invocation envelope — the parameter open/close tags, an invoke
wrapper — into a string argument (name / body), and kaeru stored it
verbatim. Observed in the field: a cite body ended with
…not a firmware toggle.</body>\n<parameter name="initiative">rack, and
because the initiative collapsed into the body text the node also
landed un-scoped.

Treating whatever arrives as trusted is the server's bug, not the
caller's.

Fix

New kaeru_core::sanitize::strip_tool_call_markup removes a leaked
envelope at the write boundary. It is deliberately narrow — keyed
to the specific tool-call markers (matching both plain and
antml:-namespaced spellings), never angle-bracket markup in general —
so legitimate content survives untouched: code (Vec<u8>), XML/HTML
snippets, even a literal </body> in prose. High precision: it only
fires on an actual leak.

Applied inside the write primitives — cite, write_episode, jot,
improve — so every adapter (MCP, rig, cloud ingest) gets clean
storage, not just one. The MCP capture/revise handlers add a
(note: stripped leaked tool-call markup from …) line so the caller is
told sanitization happened (policy: strip + flag, not silent, not reject).

Tests

  • Sanitizer units: observed leak, namespaced form, bare trailing close
    tag, wholly-envelope → empty, and legitimate-markup preservation
    (code / comparisons / HTML-ish tags pass through unchanged).
  • cite wiring test: a dirty body is stored scrubbed.

kaeru-core 140 green, kaeru-mcp 20 green. Independent of #61/#62 (no
substrate/schema change).

🤖 Generated with Claude Code

widgetii and others added 2 commits August 21, 2026 16:51
kaeru is an MCP server whose callers are arbitrary LLMs; a malformed tool
call can spill the invocation envelope (`<parameter name="...">`,
`</parameter>`, an invoke wrapper) into a string argument and get stored
verbatim, polluting the graph. Since the server can't control how a model
formats a call, it now defends at the write boundary.

New `kaeru_core::sanitize::strip_tool_call_markup` removes a leaked
envelope. It is deliberately NARROW — keyed to the specific tool-call
markers (matching plain and `antml:`-namespaced spellings), never
angle-bracket markup in general — so legitimate content (`Vec<u8>`, XML
snippets, a literal `</body>` in prose) passes through untouched.

Applied inside the write primitives (`cite`, `write_episode`, `jot`,
`improve`) so every adapter gets clean storage, not just MCP. The MCP
capture/revise handlers surface a `(note: stripped leaked tool-call
markup from ...)` line so the caller knows sanitization happened.

Tests: sanitizer unit tests (observed leak, namespaced form, trailing
close tag, wholly-envelope, and legitimate-markup preservation) plus a
cite wiring test asserting the stored body is scrubbed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 55bd449d1c5d9f4cbf3bac2c9549c832b4bb64bd)
Co-Authored-By: Claude Opus 4.8 <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