GHSA-7GCF-G7XR-8HXJ

Vulnerability from github – Published: 2026-07-15 22:41 – Updated: 2026-07-15 22:41
VLAI
Summary
serde_with: KeyValueMap serialization panics on empty sequence or map entries
Details

Summary

The 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<_>")] can be crashed by an empty inner sequence or map entry.

Details

The affected public surface includes:

  • Serialization of #[serde_as(as = "KeyValueMap<_>")] values through serde_json::to_string or any other Serde serializer`
  • Public KeyValueMap conversions for sequence and map-backed entries`

The 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.

The vulnerable data/control flow is: attacker-controlled empty entry -> serde_json::to_string -> KeyValueMap<TAs>::serialize_as -> SeqAsMapSerializer::{serialize_seq,serialize_map} -> Vec::with_capacity(len - 1) or Vec::with_capacity(len.unwrap_or(17) - 1) -> panic

Relevant source locations:

  • serde_with/src/key_value_map.rs:590
  • serde_with/src/key_value_map.rs:599
  • serde_with/src/key_value_map.rs:613
  • serde_with/src/key_value_map.rs:632
  • serde_with/src/key_value_map.rs:648

PoC

/*
[dependencies]
serde = {version = "*", features = ["derive"]}
serde_with = "*"
serde_json = "*"
*/

use serde::Serialize;
use serde_with::{serde_as, KeyValueMap};

#[derive(Serialize)]
#[serde(transparent)]
struct Seq(Vec<String>);

#[serde_as]
#[derive(Serialize)]
#[serde(transparent)]
struct KVMap {
    #[serde_as(as = "KeyValueMap<_>")]
    foo: Vec<Seq>,
}

fn main() {
    let value = KVMap {
        foo: vec![Seq(Vec::new())],
    };
    let _ = serde_json::to_string(&value).unwrap();
}

Impact

A local attacker who can trigger serialization of attacker-controlled data through KeyValueMap can terminate the process, causing a denial of service.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "serde_with"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.21.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-20"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-15T22:41:01Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### 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.",
  "id": "GHSA-7gcf-g7xr-8hxj",
  "modified": "2026-07-15T22:41:01Z",
  "published": "2026-07-15T22:41:01Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/jonasbb/serde_with/security/advisories/GHSA-7gcf-g7xr-8hxj"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jonasbb/serde_with/pull/966"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jonasbb/serde_with/commit/c8a1d820ea25df01692b367058d587343e199389"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/jonasbb/serde_with"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jonasbb/serde_with/releases/tag/v3.21.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "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",
      "type": "CVSS_V4"
    }
  ],
  "summary": "serde_with: KeyValueMap serialization panics on empty sequence or map entries"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…