Skip to content

fix: Replace NULL sentinels in form data and tolerate malformed validation errors - #646

Merged
razor-x merged 3 commits into
mainfrom
claude/python-sdk-audit-o2iid9-13-null-data-validation
Aug 28, 2026
Merged

fix: Replace NULL sentinels in form data and tolerate malformed validation errors#646
razor-x merged 3 commits into
mainfrom
claude/python-sdk-audit-o2iid9-13-null-data-validation

Conversation

@razor-x

@razor-x razor-x commented Aug 27, 2026

Copy link
Copy Markdown
Member

What

Two small hardening fixes from the SDK audit's L5 grab-bag:

NULL in form data (L5c). The client's request override applied replace_null to json= bodies and search params but not to data= — so the documented NULL sentinel form-encoded via str() as the literal string "NULL". No generated route uses data=, but it is part of the documented seam.client.post(...) escape hatch. Mapping-shaped data= now gets the same replace_null pass in both clients (name=NULL&kept=valuename=&kept=value).

Malformed validation_errors shapes (L5d). SeamHttpInvalidInputError trusted the server's validation_errors envelope: a list/string envelope, or a parameter entry that isn't a dict, raised AttributeError from inside the accessors — and the validation_errors property added in #631 walks every key, so a single oddly-shaped entry blew up the whole accessor. Both accessors now degrade to "no validation details" ([]) for anything but the expected object-of-objects shape, while well-formed entries next to malformed ones still surface.

Also teaches the test suite's recording server to record form-encoded bodies as text instead of failing to JSON-parse them.

Testing

New test/null_data_test.py: wire assertion that the sentinel form-encodes as an empty value; list/string envelopes and non-dict/non-list parameter values return [] without raising, with well-formed siblings intact.

Revert check: with seam/client.py and seam/exceptions.py reverted, the tests fail with the audit's symptoms — name=NULL&kept=value on the wire and AttributeError: 'list' object has no attribute 'get'.

Full suite: 190 passed; mypy, pylint (10.00), black clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY


Generated by Claude Code

@razor-x
razor-x requested a review from a team as a code owner August 27, 2026 22:02
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-13-null-data-validation branch from 0d27b3b to d04b935 Compare August 28, 2026 19:30
…ation errors

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-13-null-data-validation branch from d04b935 to a8c8775 Compare August 28, 2026 20:43
Comment thread seam/exceptions.py Outdated
@razor-x
razor-x merged commit 356d01f into main Aug 28, 2026
23 checks passed
@razor-x
razor-x deleted the claude/python-sdk-audit-o2iid9-13-null-data-validation branch August 28, 2026 21:42
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.

2 participants