{"id":"GHSA-7gcf-g7xr-8hxj","aliases":[],"status":"published","title":"serde_with: KeyValueMap serialization panics on empty sequence or map entries","description":"### Summary\n\nThe public `KeyValueMap` serializer assumes that each mapped element has at least one field or item to use as the map key, but it subtracts `1` from the caller-visible length before validating that assumption. An application that serializes attacker-controlled data through `#[serde_as(as = \"KeyValueMap\u003c_\u003e\")]` can be crashed by an empty inner sequence or map entry.\n\n### Details\n\nThe affected public surface includes:\n\n- Serialization of `#[serde_as(as = \"KeyValueMap\u003c_\u003e\")]` values through `serde_json::to_string` or any other Serde serializer`\n- Public `KeyValueMap` conversions for sequence and map-backed entries`\n\nThe root cause is: The `KeyValueMap` serializer preallocating `Vec::with_capacity(len - 1)` or `Vec::with_capacity(len.unwrap_or(17) - 1)` before checking that the element actually contains the required first key field or item.\n\nThe vulnerable data/control flow is: attacker-controlled empty entry -\u003e `serde_json::to_string` -\u003e `KeyValueMap\u003cTAs\u003e::serialize_as` -\u003e `SeqAsMapSerializer::{serialize_seq,serialize_map}` -\u003e `Vec::with_capacity(len - 1)` or `Vec::with_capacity(len.unwrap_or(17) - 1)` -\u003e panic\n\nRelevant source locations:\n\n- `serde_with/src/key_value_map.rs:590`\n- `serde_with/src/key_value_map.rs:599`\n- `serde_with/src/key_value_map.rs:613`\n- `serde_with/src/key_value_map.rs:632`\n- `serde_with/src/key_value_map.rs:648`\n\n### PoC\n\n```rust\n/*\n[dependencies]\nserde = {version = \"*\", features = [\"derive\"]}\nserde_with = \"*\"\nserde_json = \"*\"\n*/\n\nuse serde::Serialize;\nuse serde_with::{serde_as, KeyValueMap};\n\n#[derive(Serialize)]\n#[serde(transparent)]\nstruct Seq(Vec\u003cString\u003e);\n\n#[serde_as]\n#[derive(Serialize)]\n#[serde(transparent)]\nstruct KVMap {\n    #[serde_as(as = \"KeyValueMap\u003c_\u003e\")]\n    foo: Vec\u003cSeq\u003e,\n}\n\nfn main() {\n    let value = KVMap {\n        foo: vec![Seq(Vec::new())],\n    };\n    let _ = serde_json::to_string(\u0026value).unwrap();\n}\n```\n\n### Impact\n\nA local attacker who can trigger serialization of attacker-controlled data through `KeyValueMap` can terminate the process, causing a denial of service.","severity":{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium","from":"ghsa"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-20"],"published":"2026-07-15T22:41:01Z","modified":"2026-09-10T03:51:10Z","fixes":[{"ecosystem":"crates.io","package":"serde_with","fixed_in":["3.21.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"crates.io","package":"serde_with","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.3.0"},{"fixed":"3.21.0"}]}]},{"source":"osv","ecosystem":"crates.io","package":"serde_with","ranges":[{"type":"SEMVER","events":[{"introduced":"2.3.0"},{"fixed":"3.21.0"}]}]}],"references":[{"url":"https://github.com/jonasbb/serde_with/security/advisories/GHSA-7gcf-g7xr-8hxj","tags":["web"]},{"url":"https://github.com/jonasbb/serde_with/pull/966","tags":["web"]},{"url":"https://github.com/jonasbb/serde_with/commit/c8a1d820ea25df01692b367058d587343e199389","tags":["web"]},{"url":"https://github.com/jonasbb/serde_with/releases/tag/v3.21.0","tags":["web"]},{"url":"https://github.com/jonasbb/serde_with/compare/v2.2.0...v2.3.0","tags":["web"]},{"url":"https://github.com/advisories/GHSA-7gcf-g7xr-8hxj"},{"url":"https://github.com/jonasbb/serde_with","tags":["package"]}],"sources":{"ghsa":[{"id":"GHSA-7gcf-g7xr-8hxj","title":"serde_with: KeyValueMap serialization panics on empty sequence or map entries","description":"### Summary\n\nThe public `KeyValueMap` serializer assumes that each mapped element has at least one field or item to use as the map key, but it subtracts `1` from the caller-visible length before validating that assumption. An application that serializes attacker-controlled data through `#[serde_as(as = \"KeyValueMap\u003c_\u003e\")]` can be crashed by an empty inner sequence or map entry.\n\n### Details\n\nThe affected public surface includes:\n\n- Serialization of `#[serde_as(as = \"KeyValueMap\u003c_\u003e\")]` values through `serde_json::to_string` or any other Serde serializer`\n- Public `KeyValueMap` conversions for sequence and map-backed entries`\n\nThe root cause is: The `KeyValueMap` serializer preallocating `Vec::with_capacity(len - 1)` or `Vec::with_capacity(len.unwrap_or(17) - 1)` before checking that the element actually contains the required first key field or item.\n\nThe vulnerable data/control flow is: attacker-controlled empty entry -\u003e `serde_json::to_string` -\u003e `KeyValueMap\u003cTAs\u003e::serialize_as` -\u003e `SeqAsMapSerializer::{serialize_seq,serialize_map}` -\u003e `Vec::with_capacity(len - 1)` or `Vec::with_capacity(len.unwrap_or(17) - 1)` -\u003e panic\n\nRelevant source locations:\n\n- `serde_with/src/key_value_map.rs:590`\n- `serde_with/src/key_value_map.rs:599`\n- `serde_with/src/key_value_map.rs:613`\n- `serde_with/src/key_value_map.rs:632`\n- `serde_with/src/key_value_map.rs:648`\n\n### PoC\n\n```rust\n/*\n[dependencies]\nserde = {version = \"*\", features = [\"derive\"]}\nserde_with = \"*\"\nserde_json = \"*\"\n*/\n\nuse serde::Serialize;\nuse serde_with::{serde_as, KeyValueMap};\n\n#[derive(Serialize)]\n#[serde(transparent)]\nstruct Seq(Vec\u003cString\u003e);\n\n#[serde_as]\n#[derive(Serialize)]\n#[serde(transparent)]\nstruct KVMap {\n    #[serde_as(as = \"KeyValueMap\u003c_\u003e\")]\n    foo: Vec\u003cSeq\u003e,\n}\n\nfn main() {\n    let value = KVMap {\n        foo: vec![Seq(Vec::new())],\n    };\n    let _ = serde_json::to_string(\u0026value).unwrap();\n}\n```\n\n### Impact\n\nA local attacker who can trigger serialization of attacker-controlled data through `KeyValueMap` can terminate the process, causing a denial of service.","status":"published","published":"2026-07-15T22:41:01Z","modified":"2026-08-31T14:18:16Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium"}],"cwes":["CWE-20"],"updated_at":"2026-11-02T14:41:08.084849Z"}],"osv":[{"id":"GHSA-7gcf-g7xr-8hxj","title":"serde_with: KeyValueMap serialization panics on empty sequence or map entries","description":"### Summary\n\nThe public `KeyValueMap` serializer assumes that each mapped element has at least one field or item to use as the map key, but it subtracts `1` from the caller-visible length before validating that assumption. An application that serializes attacker-controlled data through `#[serde_as(as = \"KeyValueMap\u003c_\u003e\")]` can be crashed by an empty inner sequence or map entry.\n\n### Details\n\nThe affected public surface includes:\n\n- Serialization of `#[serde_as(as = \"KeyValueMap\u003c_\u003e\")]` values through `serde_json::to_string` or any other Serde serializer`\n- Public `KeyValueMap` conversions for sequence and map-backed entries`\n\nThe root cause is: The `KeyValueMap` serializer preallocating `Vec::with_capacity(len - 1)` or `Vec::with_capacity(len.unwrap_or(17) - 1)` before checking that the element actually contains the required first key field or item.\n\nThe vulnerable data/control flow is: attacker-controlled empty entry -\u003e `serde_json::to_string` -\u003e `KeyValueMap\u003cTAs\u003e::serialize_as` -\u003e `SeqAsMapSerializer::{serialize_seq,serialize_map}` -\u003e `Vec::with_capacity(len - 1)` or `Vec::with_capacity(len.unwrap_or(17) - 1)` -\u003e panic\n\nRelevant source locations:\n\n- `serde_with/src/key_value_map.rs:590`\n- `serde_with/src/key_value_map.rs:599`\n- `serde_with/src/key_value_map.rs:613`\n- `serde_with/src/key_value_map.rs:632`\n- `serde_with/src/key_value_map.rs:648`\n\n### PoC\n\n```rust\n/*\n[dependencies]\nserde = {version = \"*\", features = [\"derive\"]}\nserde_with = \"*\"\nserde_json = \"*\"\n*/\n\nuse serde::Serialize;\nuse serde_with::{serde_as, KeyValueMap};\n\n#[derive(Serialize)]\n#[serde(transparent)]\nstruct Seq(Vec\u003cString\u003e);\n\n#[serde_as]\n#[derive(Serialize)]\n#[serde(transparent)]\nstruct KVMap {\n    #[serde_as(as = \"KeyValueMap\u003c_\u003e\")]\n    foo: Vec\u003cSeq\u003e,\n}\n\nfn main() {\n    let value = KVMap {\n        foo: vec![Seq(Vec::new())],\n    };\n    let _ = serde_json::to_string(\u0026value).unwrap();\n}\n```\n\n### Impact\n\nA local attacker who can trigger serialization of attacker-controlled data through `KeyValueMap` can terminate the process, causing a denial of service.","status":"published","published":"2026-07-15T22:41:01Z","modified":"2026-09-10T03:51:10.897685062Z","cvss":[{"version":"4.0","score":5.1,"vector":"CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium"}],"cwes":["CWE-20"],"updated_at":"2026-11-02T15:46:41.002603Z"}]}}
