Repository navigation
fix(sanitize): decode and sanitize bytes fields in sanitize_dict - #316
Merged
Merged
Conversation
sanitize_dict sanitized only str values; bytes fields were decoded later by _json_default at serialization time, i.e. after the sanitization point, so a control byte stripped from str fields survived raw in bytes fields. Decode bytes (UTF-8, replacing errors) inside sanitize_dict so both field types get identical treatment. _json_default stays as the last resort for bytes that reach json.dumps without passing sanitize_dict. Co-Authored-By: Claude Code <[email protected]>
chigwell
approved these changes
Oct 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sanitize_dictsanitized onlystrvalues;bytesfields were decoded later by_json_defaultat serialization time — after the sanitization point. The same control byte was stripped from str fields but survived raw in bytes fields, then round-tripped back out throughformat_tool_result(...)→json.loads.sanitize_dictnow decodesbytes(UTF-8, replacing errors) at the sanitization point and sanitizes them as text, so both field types get identical treatment._json_defaultstays as the last resort for bytes that reachjson.dumpswithout passing throughsanitize_dict.Fixes #305
Before
format_tool_result(...)then round-tripped the raw ESC sequence back out throughjson.loads— identical content got different treatment depending on the field type.After
Bytes fields now return sanitized
str— the same shape_json_defaultproduced at serialization time, so the final JSON output is unchanged except that control bytes are gone.Tests
tests/test_sanitize.py::TestSanitizeDict::test_bytes_values_are_decoded_and_sanitized— ESC byte stripped from a bytes field, valid UTF-8 payload (café\x00) decoded and cleaned.pytest -q→ 1216 passed.Risks
sanitize_dictoutput type changes for bytes fields:bytes→ sanitizedstr. This matches the final JSON serialization shape; no caller in the repo relies on bytes survivingsanitize_dict.🤖 Generated with Claude Code