You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Non-json client configs: no nesting-depth cap (json5/yaml resource spike) and silent big-integer rounding on rewrite (toml/json5/yaml) #1635
While reviewing #1631/#1632, adversarial measurement passes found two classes of pre-existing exposure in the client-config rewrite pipeline for the non-json formats. Neither is introduced or enlarged by #1632 (which guards the json path); both exist on dev today for every first apply onto a foreign config file, and are reported here so they don't get lost.
1. No nesting-depth cap for json5/yaml (resource spike + raw error instead of structured refusal). parseConfig has no depth guard for json5 and yaml (the json path gets one in the follow-up to #1632). Measured on Bun 1.3.14/JSC through the exact layers the writer calls (parseConfig → merge clone → serializeDocument): an openclaw json5 config nested 15,000 deep (bounded by the parser's own stack ceiling ~15,295) produces a ~450MB output string at ~1.1GB peak RSS in ~1s per management request; yaml accepts ~3,000 levels and drives the recursive renderYaml. Reachability requires local write access to a client config plus an authenticated management mutation — so a hardening issue, not an urgent vulnerability.
2. Big-integer literals silently rounded for toml/json5/yaml. Bun.TOML.parse, Bun.JSON5.parse and Bun.YAML.parse all round 9007199254740993 to 9007199254740992, and the corresponding renderers write the rounded value back without refusal. A first apply onto e.g. a kimi config.toml holding session_id = 9007199254740993 as a sibling rewrites it to …992 and reports success — exactly the failure class the TOML inf/nan guard (and, since #1632, the json number scan) treats as "a silent value change is worse than a refusal". json5 additionally loses -0 (Bun.JSON5.stringify({a:-0}) → {a:0}) while non-finite values are safe there (JSON5 can represent Infinity).
Suggested direction, mirroring the json approach: per-format raw-text or post-parse round-trip checks that classify such files unsafe before any rewrite, plus a shared nesting ceiling. I'm happy to pick this up after #1632 and the depth-hardening follow-up PR land, if the direction is agreeable.
Reproduction
Depth (json5): bun -e 'const {parseConfig}=await import("./src/integrations/config-io.ts"); const t="[".repeat(15000)+"1"+"]".repeat(15000); console.log(parseConfig(t,"json5"))' → parses (no guard); feeding the parsed doc through the writer layers spikes RSS ~1.1GB.
Rounding (toml): create a kimi config with a sibling session_id = 9007199254740993, no opencodex block; enable the kimi integration → file now contains session_id = 9007199254740992, result ok.
Version
2.14.2 (reproduced against dev)
Operating system
macOS 26 (arm64), Bun 1.3.14
Provider and model
No response
Logs or error output
No response
Screenshots and supporting files
No response
Redacted configuration
No response
Checks
I searched existing issues and documentation.
I removed secrets, tokens, account details, request credentials, and personal data.
#375 - [WRONG BRANCH] fix(cursor): estimate context after restart [closed] #886 - fix(server,config): extension CORS origin identity + symlink-safe atomic writes [open] #892 - fix: bound the six remaining retained-state leaks (#820 wave 2) [merged] #1020 - fix(anthropic): surface upstream error bodies through sidecar bridges [merged] #1632 - fix(integrations): classify a json sibling edit as stale instead of conflict [open]
📝 Issue Planner
Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.
Create Plan
🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your .coderabbit.yaml:
issue_enrichment:
auto_enrich:
enabled: false
💬 Have feedback or questions? Drop into our discord!
Confirmed against current dev (040f6db5b). This is not fixed there.
src/integrations/config-io.ts:31-33 hands JSON5 and YAML directly to Bun parsers, and src/integrations/config-io.ts:47 does the same for TOML after only an inf/nan raw-text guard. src/integrations/merge.ts:18-20 then JSON-clones the parsed user document, while src/integrations/serialize.ts:225-233 re-renders it. A sibling literal 9007199254740993 is parsed and written back as 9007199254740992 for TOML, JSON5, and YAML, so a successful apply can silently change user data. JSON5 also parses -0 and serializes it as 0.
The depth report is also substantiated for JSON5: there is no format-specific depth limit before parse or serialization, and a 15,000-level nested-object JSON5 document reaches the whole-document renderer and produces roughly a 450 MB output string locally. YAML's exact parser ceiling is runtime- and input-shape-dependent, but renderYaml recursively traverses user-supplied arrays and records at src/integrations/serialize.ts:119-135, with no explicit integration-level nesting policy.
#1637 intentionally covers strict JSON only; it does not close these JSON5/YAML/TOML paths. The follow-up should add format-appropriate pre-rewrite value-integrity checks and bounded nesting, with writer-level tests proving that refusal leaves the original bytes unchanged.
Both halves fixed: (1) nesting-depth cap by PR #1637 (23f4349 hardening: fold the depth ceiling into the safety scan), (2) numeric round-trip refusal by 43ef83f (fix(integrations): guard the rewrite against non-round-tripping numbers). Both in dev and main.
Activity
coderabbitai commentedon Aug 13, 2026
🔗 Related PRs
#375 - [WRONG BRANCH] fix(cursor): estimate context after restart [closed]
#886 - fix(server,config): extension CORS origin identity + symlink-safe atomic writes [open]
#892 - fix: bound the six remaining retained-state leaks (
#820wave 2) [merged]#1020 - fix(anthropic): surface upstream error bodies through sidecar bridges [merged]
#1632 - fix(integrations): classify a json sibling edit as stale instead of conflict [open]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
lidge-jun commentedon Aug 13, 2026
Confirmed against current
dev(040f6db5b). This is not fixed there.src/integrations/config-io.ts:31-33hands JSON5 and YAML directly to Bun parsers, andsrc/integrations/config-io.ts:47does the same for TOML after only aninf/nanraw-text guard.src/integrations/merge.ts:18-20then JSON-clones the parsed user document, whilesrc/integrations/serialize.ts:225-233re-renders it. A sibling literal9007199254740993is parsed and written back as9007199254740992for TOML, JSON5, and YAML, so a successful apply can silently change user data. JSON5 also parses-0and serializes it as0.The depth report is also substantiated for JSON5: there is no format-specific depth limit before parse or serialization, and a 15,000-level nested-object JSON5 document reaches the whole-document renderer and produces roughly a 450 MB output string locally. YAML's exact parser ceiling is runtime- and input-shape-dependent, but
renderYamlrecursively traverses user-supplied arrays and records atsrc/integrations/serialize.ts:119-135, with no explicit integration-level nesting policy.#1637 intentionally covers strict JSON only; it does not close these JSON5/YAML/TOML paths. The follow-up should add format-appropriate pre-rewrite value-integrity checks and bounded nesting, with writer-level tests proving that refusal leaves the original bytes unchanged.
DISPOSITION: ACCEPTED
lidge-jun commentedon Aug 14, 2026
Both halves fixed: (1) nesting-depth cap by PR #1637 (23f4349 hardening: fold the depth ceiling into the safety scan), (2) numeric round-trip refusal by 43ef83f (fix(integrations): guard the rewrite against non-round-tripping numbers). Both in dev and main.