{"id":"GHSA-cj9g-3mj2-g8vv","summary":"MessagePack-CSharp: JSON conversion APIs can recurse without consistent depth enforcement","details":"## Summary\n\nMessagePack-CSharp's JSON conversion helpers contain multiple recursion paths that do not consistently enforce a depth limit. These paths are in the JSON conversion component rather than normal typed MessagePack deserialization.\n\nThree related issues are covered by this advisory:\n\n1. `MessagePackSerializer.ConvertFromJson` recursively processes nested JSON arrays and objects in `FromJsonCore()` without consulting `MessagePackSecurity.MaximumObjectGraphDepth`.\n2. `TinyJsonReader.ReadNextToken()` recursively consumes comma and colon separator characters, allowing even malformed JSON with long separator runs to consume one stack frame per character.\n3. `MessagePackSerializer.ConvertToJson` applies depth checks to arrays and maps, but the typeless extension branch for ext-100 recursively calls `ToJsonCore()` without applying `MessagePackSecurity.DepthStep(ref reader)`.\n\nEach path can allow attacker-controlled input to exhaust the process stack and trigger an uncatchable `StackOverflowException` instead of failing with a catchable parse or serialization exception.\n\n## Impact\n\nApplications are affected when they call MessagePack-CSharp JSON conversion APIs on attacker-controlled data. This includes gateways, diagnostics endpoints, migration tools, logging paths, and services that convert between external JSON and MessagePack payloads.\n\nFor JSON-to-MessagePack conversion, deeply nested JSON arrays or objects can recurse through `FromJsonCore()` without applying the configured object graph depth limit. Separately, long runs of comma or colon separator characters can recurse through `TinyJsonReader.ReadNextToken()` before normal structural validation rejects the input.\n\nFor MessagePack-to-JSON conversion, nested typeless extension wrappers can recurse through `ToJsonCore()` without the depth guard that the same function applies to arrays and maps.\n\n`MessagePackSecurity.UntrustedData` does not fully mitigate these conversion paths because the missing checks occur inside JSON conversion and tokenization branches that do not consistently use the configured depth policy.\n\n## Affected components\n\n- Package: `MessagePack`\n- APIs: `MessagePackSerializer.ConvertFromJson`, `MessagePackSerializer.ConvertToJson`\n- Internal routines: `FromJsonCore`, `ToJsonCore`, `TinyJsonReader.ReadNextToken`\n- Data shapes: deeply nested JSON arrays/objects, long JSON separator runs, and nested typeless MessagePack extension values converted to JSON\n- Finding IDs: `MESSAGEPACKCSHARP-090`, `MESSAGEPACKCSHARP-091`, `MESSAGEPACKCSHARP-092`\n\n## Patches\n\nFixes are prepared and will be released in coordinated patch versions.\n\nUpgrade guidance:\n\n1. Upgrade `MessagePack` to the patched version for your release line.\n2. Upgrade companion MessagePack packages in the same dependency graph to the coordinated patched versions.\n\nThe JSON-to-MessagePack fix should add explicit JSON nesting-depth accounting to `FromJsonCore`, using the configured maximum object graph depth or an equivalent limit, or rewrite the conversion to use an iterative bounded stack.\n\nThe tokenizer fix should replace separator self-recursion in `TinyJsonReader.ReadNextToken()` with an iterative loop so consecutive commas, colons, and whitespace do not consume stack frames.\n\nThe MessagePack-to-JSON fix should apply `DepthStep` and matching `reader.Depth--` cleanup around recursive `ToJsonCore()` calls made from the typeless extension branch, consistent with the existing array and map conversion branches.\n\n## Workarounds\n\nPatching is recommended.\n\nUntil a patched version is available, do not pass untrusted JSON directly to `ConvertFromJson`, and do not call `ConvertToJson` on untrusted MessagePack payloads that may contain typeless extension values. Validate JSON nesting depth with a parser that enforces depth limits before calling MessagePack-CSharp, reject malformed JSON before conversion, and apply strict input-size limits.\n\nInput-size limits reduce exposure but do not remove the recursive behavior in affected versions.\n\n## References\n\n- `MESSAGEPACKCSHARP-090`: `ConvertFromJson` unbounded structural recursion\n- `MESSAGEPACKCSHARP-091`: `TinyJsonReader.ReadNextToken` separator self-recursion\n- `MESSAGEPACKCSHARP-092`: `ConvertToJson` ext-100 branch missing depth enforcement\n- CWE-674: Uncontrolled Recursion\n\n## CVE split rationale\n\nThese issues are grouped because they affect the same JSON conversion feature area and share the same failure mode: recursive conversion/tokenization paths do not consistently enforce depth or iteration bounds for attacker-controlled input. They are distinct from normal binary MessagePack skip recursion, dynamic union formatter depth accounting, DateTime stack allocation, and allocation-oriented denial-of-service issues.","aliases":["CVE-2026-48512"],"modified":"2026-06-25T20:11:29.518467Z","published":"2026-06-25T19:51:36Z","database_specific":{"nvd_published_at":"2026-06-22T22:16:47Z","cwe_ids":["CWE-674"],"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-06-25T19:51:36Z"},"references":[{"type":"WEB","url":"https://github.com/MessagePack-CSharp/MessagePack-CSharp/security/advisories/GHSA-cj9g-3mj2-g8vv"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-48512"},{"type":"PACKAGE","url":"https://github.com/MessagePack-CSharp/MessagePack-CSharp"}],"affected":[{"package":{"name":"MessagePack","ecosystem":"NuGet","purl":"pkg:nuget/MessagePack"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.5.301"}]}],"versions":["0.1.0-beta","0.2.0-beta","0.2.1-beta","0.2.2-beta","0.2.3-beta","0.3.0-beta","0.4.0","0.4.1","0.4.2","0.5.0","0.6.0","0.6.1","0.7.0","0.7.2","0.8.0","0.8.1","0.8.2","0.8.3","0.8.4","0.8.5","1.0.0","1.0.1","1.0.2","1.0.3","1.1.0","1.1.1","1.1.1.1","1.1.2","1.2.0","1.2.0.1","1.2.0.2","1.2.1","1.2.2","1.2.3","1.3.0","1.3.1","1.3.1.1","1.3.2","1.3.3","1.4.0","1.4.1","1.4.2","1.4.3","1.4.4","1.5.0","1.5.0.1","1.5.0.2","1.5.1","1.6.0","1.6.0.1","1.6.0.2","1.6.0.3","1.6.1","1.6.1.1","1.6.1.2","1.6.2","1.7.0","1.7.1","1.7.2","1.7.3","1.7.3.1","1.7.3.2","1.7.3.3","1.7.3.4","1.7.3.7","1.8.71-beta","1.8.74","1.8.80","1.9.11","1.9.3","1.9.3-g129239b107","2.0.107-alpha","2.0.108-alpha","2.0.110-alpha","2.0.110-alpha-g1e44a9106f","2.0.119-beta","2.0.123-beta","2.0.171-beta","2.0.204-beta","2.0.221-beta","2.0.231-rc","2.0.270-rc","2.0.299-rc","2.0.323","2.0.335","2.1.115","2.1.143","2.1.152","2.1.165","2.1.194","2.1.80","2.1.90","2.2.113","2.2.36-alpha","2.2.44-rc","2.2.60","2.2.85","2.3.112","2.3.58-alpha","2.3.73-alpha","2.3.75","2.3.85","2.4.14-alpha","2.4.23-alpha","2.4.35","2.4.59","2.5.103","2.5.108","2.5.124","2.5.129","2.5.140","2.5.168","2.5.171","2.5.172","2.5.187","2.5.192","2.5.198","2.5.205","2.5.64-alpha","2.5.94"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-cj9g-3mj2-g8vv/GHSA-cj9g-3mj2-g8vv.json"}},{"package":{"name":"MessagePack","ecosystem":"NuGet","purl":"pkg:nuget/MessagePack"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0"},{"fixed":"3.1.7"}]}],"versions":["3.0.111-alpha","3.0.129-beta","3.0.134-beta","3.0.208-rc-0001","3.0.3","3.0.300","3.0.308","3.0.54-alpha","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4","3.1.5","3.1.6"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-cj9g-3mj2-g8vv/GHSA-cj9g-3mj2-g8vv.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"}]}