Sanitize Unicode tags in Responses output - #10745
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 141f58d88a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5724065e14
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 98e9d3d01f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2de9e90e73
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6ef1051539
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d0e2bd84f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b38e07fa4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
* origin/main: fix(mcp): prune dead notification subscribers (#11032) chore: remove the extension and tool count suggestion (#10869) feat: compaction in the GDK (#11042) fix(provider): retry transient errors on first stream item before ending turn (#10968) feat(cli): add /new to start a fresh session without restarting (#10767) feat(acp): title new sessions from _meta.sessionTitle (#10712) fix: adjust rmcp::model::Meta ref (#11107) Skip hook loading and lifecycle events for subagents (#10596) Sanitize Unicode tags in Responses output (#10745) fix(conversation): sanitize nested tool responses (#10609) fix(hints): bound recursive file expansion (#10546) fix(providers): drop stale signed thinking blocks after a mid-conversation model switch (#10007) fix(desktop): clarify compact cost display (#11093) Index messages by (session_id, created_timestamp, id) to stop on-disk sort storms (#10874) docs: add tool shim guide covering when to enable, backends, and troubleshooting (#10858) fix(deep-link): route extension/session deep links to regular windows not standalone app windows (#10908) fix(ui): raise chat input z-index so slash menu appears above loading indicator (#11015) fix(ui): support remote working directory for external backend (#10827)
* main: fix(mcp): prune dead notification subscribers (#11032) chore: remove the extension and tool count suggestion (#10869) feat: compaction in the GDK (#11042) fix(provider): retry transient errors on first stream item before ending turn (#10968) feat(cli): add /new to start a fresh session without restarting (#10767) feat(acp): title new sessions from _meta.sessionTitle (#10712) fix: adjust rmcp::model::Meta ref (#11107) Skip hook loading and lifecycle events for subagents (#10596) Sanitize Unicode tags in Responses output (#10745) fix(conversation): sanitize nested tool responses (#10609) fix(hints): bound recursive file expansion (#10546) fix(providers): drop stale signed thinking blocks after a mid-conversation model switch (#10007) fix(desktop): clarify compact cost display (#11093) Index messages by (session_id, created_timestamp, id) to stop on-disk sort storms (#10874) docs: add tool shim guide covering when to enable, backends, and troubleshooting (#10858) fix(deep-link): route extension/session deep links to regular windows not standalone app windows (#10908) fix(ui): raise chat input z-index so slash menu appears above loading indicator (#11015) fix(ui): support remote working directory for external backend (#10827)
Summary
Sanitize Unicode tag characters as Responses-compatible provider output enters conversation history.
This restores the invariant that model-visible text cannot contain invisible Unicode-tag instructions absent from user-visible rendering. The fix covers non-streaming
output_textandrefusalblocks, completed streaming output items, live text/refusal deltas, reasoning summaries stored as thinking blocks, and tool-call IDs, names, and arguments in both streaming and non-streaming response shapes.Complete narrative strings use the existing NFC-normalizing sanitizer. Live stream deltas strip tag characters without per-delta normalization, so arbitrary SSE boundaries cannot change visible output. Tool IDs, names, and recursively parsed arguments strip tag characters without normalization, covering nested arrays and objects, object keys, and escaped tag code points while preserving legitimate non-tag Unicode exactly. If distinct argument keys or tool request IDs collide after tag stripping, the provider response is rejected instead of silently choosing or misassociating a value.
Testing
cargo fmt --allcargo test -p goose-provider-types— 449 passedcargo build -p goose-provider-types -p goosecargo clippy -p goose-provider-types -p goose --all-targets -- -D warningsgit diff --checkRelated Issues
Addresses Project Loupe audit finding 612.
Rollout considerations
The sanitizer is the existing repository-wide Unicode-tag control and leaves legitimate non-tag Unicode unchanged. Streaming output and structured tool calls avoid normalization where transport or downstream consumers may depend on exact code-point sequences. Sanitization-induced key or request-ID ambiguity fails closed.
This finding was discovered by Project Loupe.