Strip nested tool-return files by default (outbound hardening)

Closed
DS
4mo ago
+503-26

Stacked on #5255 — one of three PRs splitting that work. The base of this PR is the ui-thread-multimodal-toolreturn branch (PR #5255), not main, so the diff shows only this PR's changes. It will be retargeted to main once #5255 merges.

What this adds

Outbound secure-default file-strip hardening, split out of #5255. On the preserve_file_data=False default, file data can currently leak to the client through file content nested inside tool-return dicts/lists. This adds strip_tool_return_files, which recursively strips nested file data on that default, closing the server→client exposure gap.

The leak is pre-existing on main and not urgent — this is framed as GHSA hardening, not an emergency fix.

Included:

  • strip_tool_return_files (recursive nested-file strip) wired into the AG-UI and Vercel AI outbound paths on the preserve_file_data=False default
  • AG-UI orphan-sidecar guard (raise ValueError when a sidecar has no owning tool message)
  • media_type-gated Vercel _coerce_js_binary_data fix (only coerces recognized binary shapes, preserves non-multimodal kind/type dicts)
  • Tests for all of the above
  • Docs update (docs/ui/vercel-ai.md)

The #5255 split

  • A — #5255 itself, reduced to the core multimodal tool-return round-trip
  • B — this PR: outbound strip_tool_return_files secure-default hardening
  • C — inbound sanitizer (sanitize_message_history), independent of A and B

Checklist

  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • No breaking changes in accordance with the version policy.
  • PR title is fit for the release changelog.