Skip to content

fix(admin): cap configuration value nesting at 1,000 levels explicitly - #2082

Merged
dawsontoth merged 2 commits into
stagefrom
claude/admin-config-nesting-depth
Nov 11, 2026
Merged

dawsontoth merged 2 commits into
stagefrom
claude/admin-config-nesting-depth

Conversation

@dawsontoth

@dawsontoth dawsontoth commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

⊙ Problem

stage CI is red, and so is every PR's Verify PR run. The Configuration page's parseConfigValue relied on JSON.stringify throwing to refuse deeply nested values. Node 26 parses and stringifies 100,000 levels without throwing, so the value was accepted and the test crashed with RangeError: Maximum call stack size exceeded inside toEqual.

💡 Solution

  • In index.tsx, the walk that already checks numbers now counts depth too. It refuses more than MAX_CONFIG_DEPTH (1,000) nested arrays or objects with the same "nested too deeply" message, on any engine.
  • The JSON.stringify try/catch is gone, since nothing can reach it now.
  • Values up to 1,000 levels still save, as before.
  • Two review concerns: the walk allocates a small array per node (an admin-only dialog, not a hot path). Stringify has no fallback (JSON.parse output can only make it throw by running out of stack, which 1,000 levels does not).

🤔 The cap is Studio-only, at 1,000

central-manager accepts any value (Joi.any() in validatePatchConfiguration), so a direct API call can still store deeper values. A server-side cap would be a separate central-manager change. 1,000 is the depth #1988 already accepted and tested. A lower cap could refuse an existing value when someone edits it.

✅ Verification

  • Fails on base: on Node 26.13.0 (the .nvmrc pin) the old test crashes with the RangeError. With the fix it passes.
  • The test in index.test.tsx now checks .ok and .error on their own, so a regression fails an assertion instead of crashing. Removing the guard, raising the limit by one, and counting size instead of depth each fail it with an AssertionError.
  • It covers arrays and objects at the limit, one past it and at 100,000, plus 5,000 shallow siblings.
  • Full gate on Node 26.13.0: vitest 653 files / 7,243 tests, tsc -b and oxlint all pass. dprint check flags AdminShell.tsx and adminShellVisibility.test.ts, which are already unformatted on stage and not part of this PR. CI doesn't run dprint check.

🤖 Generated with Claude Code

Related PRs: #2065 overlaps (carries its own copy of this fix, with the same 1,000 limit; it should drop that copy when it rebases), 1 others independent

Complexity: easy

Review-Coverage: authored=claude; ran=cursor-composer,codex,gemini; adjudicated=domain; declined=cursor-grok,muse; urgency=fast; rounds=2; full=1 @ c13b28c

Review-Attention: read ~3m (decisions: client-only-depth-cap, depth-cap-value) @ c13b28c

dawsontoth and others added 2 commits November 10, 2026 10:02
parseConfigValue relied on JSON.stringify throwing to refuse deeply
nested values. Node 26's V8 parses and stringifies 100,000 levels
without throwing, so the 100,000-deep value was accepted and the test
crashed with a RangeError inside toEqual while comparing it. That broke
every Verify PR run and stage's own deploy.

Count depth in the existing iterative walk and refuse past
MAX_CONFIG_DEPTH (1,000 nested arrays or objects) with the same
message, whatever the engine allows. The now-unreachable try/catch
around JSON.stringify goes.

The test asserts on .ok and .error separately, so a regression fails
by assertion instead of crashing, and pins the boundary for arrays and
objects plus a wide-but-shallow value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1 found the comments restated code or narrated the next
assertion. Keep only why the depth is counted and why the test avoids
toEqual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 83.76% 19117 / 22823
🔵 Statements 83.61% 20245 / 24211
🔵 Functions 79.33% 5199 / 6553
🔵 Branches 79.06% 15885 / 20092
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/features/admin/configuration/index.tsx 91.93% 85.71% 88.88% 94.33% 84, 87, 134-135, 156
Generated in workflow #2556 for commit c13b28c by the Vitest Coverage Report Action

@dawsontoth
dawsontoth marked this pull request as ready for review November 11, 2026 16:25
@dawsontoth
dawsontoth requested a review from a team as a code owner November 11, 2026 16:25
@dawsontoth
dawsontoth merged commit 0c60574 into stage Nov 11, 2026
5 checks passed
@dawsontoth
dawsontoth deleted the claude/admin-config-nesting-depth branch November 11, 2026 16:27
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.

1 participant