fix(utils): give parse_json_body an explicit max_depth - #169
Merged
Merged
Conversation
The "nested too deeply" refusal only caught RecursionError from json.loads, and where that fires moves with every Python release: near 1,000 levels on 3.11, 20,000 on 3.13, and not before 1,000,000 on 3.14, whose C recursion guard is stack-based. The existing 20,000-level test therefore fails on 3.14. Add max_depth (default 100) alongside max_bytes, checked with an explicit-stack walk of the parsed body so the check itself cannot recurse. Keep the RecursionError catch as the fallback for a body that out-nests the interpreter before the walk runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
caterryan
force-pushed
the
fix/json-body-max-depth
branch
from
September 15, 2026 21:53
18064f4 to
518cfed
Compare
Aliaksei-Kharlap
approved these changes
Sep 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.
parse_json_bodypromised to refuse a body "nested too deeply" but only caught the interpreter'sRecursionErrorfromjson.loads. Where that fires moves with every Python release. Measured locally with"[" * n + "]" * n:RecursionErroratPython 3.14's C recursion guard is stack-based, so the existing 20,000-level test parses successfully there and
test_a_deeply_nested_body_stays_within_the_valueerror_contractfails. The CI matrix stops at 3.13, so nothing caught it. I hit it running the suite locally on 3.14 while preparing the 0.4.0 release.Change.
parse_json_bodytakesmax_depth(keyword-only, defaultDEFAULT_MAX_BODY_DEPTH = 100), mirroringmax_bytes. The parsed body is walked with an explicit stack and refused once a container sits deeper than the limit, counting the top-level object as level 1.Nonelifts the limit. Adictbody is not measured, as withmax_bytes.The
RecursionErrorcatch stays as the fallback for a body that out-nests the interpreter before the walk can run: 3.11 at 20,000 levels, or a caller who raisedmax_depthpast what the interpreter tolerates. Same "nested too deeply" prefix; the explicit refusal also names the limit.Changelog entry under Unreleased. No version bump.
Why 100. Real plugin request bodies are a handful of levels deep. 100 leaves wide headroom while sitting far below every interpreter's guard, so the explicit check is what fires everywhere and the message is the same on 3.11 and 3.14. A body deeper than 100 that 3.13 used to accept is now refused; that is the point, and
max_depthis there for a caller who needs more.Verified. The existing suite passes on 3.13 and 3.14 locally, including the 20,000-level test that failed on 3.14 before. CI covers 3.11.
🤖 Generated with Claude Code