Skip to content
Heist/ feed
Back to feed
HighFix available

Remote DoS through unchecked `IdList` allocation in negentropy

Type: advisorySources: OSV

## Summary The `negentropy` crate is vulnerable to denial-of-service through an unchecked, peer-controlled ID count in reconciliation messages. With the `std` feature enabled, which is the default configuration, a small malformed message can trigger an enormous memory allocation and terminate the application. ## Details When processing an `IdList` range, the reconciliation parser uses the peer-provided ID count to reserve memory before checking whether the message contains the corresponding IDs: ```rust let mut their_elems: HashSet = HashSet::with_capacity(num_ids as usize); ``` An attacker can declare an arbitrarily large count without supplying any IDs. The allocation occurs before the parser reaches the ID-reading loop, which would otherwise reject the truncated message. With Rust's default allocation-error behavior, a failed allocation aborts the process rather than unwinding. Consequently, `catch_unwind` cannot contain the failure. Both `reconcile` and `reconcile_with_ids` reach the vulnerable parser. The patched versions validate the count against the remaining message length before allocating: ```rust if num_ids > (query.len() / ID_SIZE) as u64 { return Err(Error::ParseEndsPrematurely); } ``` ## Impact An unauthenticated remote attacker can terminate an application that exposes reconciliation to untrusted peers without additional validation. For example, a Nostr relay that forwards `NEG-OPEN` or `NEG-MSG` reconciliation payloads to the vulnerable parser can be taken do

Products
negentropy
Affected versions
Not specified
Fixed versions
0.4.4, 0.5.2
CVEs
Not specified
Confirmed fixed CVEs
Not specified
Updated in this feed
30 Oct 2026, 23:06 UTC · Revision 1

Source evidence

Remote DoS through unchecked `IdList` allocation in negentropy

core-osv · Original source

Published 14 Oct 2026, 12:00 UTC

## Summary The `negentropy` crate is vulnerable to denial-of-service through an unchecked, peer-controlled ID count in reconciliation messages. With the `std` feature enabled, which is the default configuration, a small malformed message can trigger an enormous memory allocation and terminate the application. ## Details When processing an `IdList` range, the reconciliation parser uses the peer-provided ID count to reserve memory before checking whether the message contains the corresponding IDs: ```rust let mut their_elems: HashSet = HashSet::with_capacity(num_ids as usize); ``` An attacker can declare an arbitrarily large count without supplying any IDs. The allocation occurs before the parser reaches the ID-reading loop, which would otherwise reject the truncated message. With Rust's default allocation-error behavior, a failed allocation aborts the process rather than unwinding. Consequently, `catch_unwind` cannot contain the failure. Both `reconcile` and `reconcile_with_ids` reach the vulnerable parser. The patched versions validate the count against the remaining message length before allocating: ```rust if num_ids > (query.len() / ID_SIZE) as u64 { return Err(Error::ParseEndsPrematurely); } ``` ## Impact An unauthenticated remote attacker can terminate an application that exposes reconciliation to untrusted peers without additional validation. For example, a Nostr relay that forwards `NEG-OPEN` or `NEG-MSG` reconciliation payloads to the vulnerable parser can be taken do

osv:RUSTSEC-2026-0365

negentropy

Fixed versions: 0.4.4, 0.5.2

Complete source record
{
  "id": "0f09ebb737daff17a44937ab70cd8af9f2ca6aab3d630c2a2247cab73f08169a",
  "url": "https://osv.dev/vulnerability/RUSTSEC-2026-0365",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "title": "Remote DoS through unchecked `IdList` allocation in negentropy",
    "summary": "## Summary The `negentropy` crate is vulnerable to denial-of-service through an unchecked, peer-controlled ID count in reconciliation messages. With the `std` feature enabled, which is the default configuration, a small malformed message can trigger an enormous memory allocation and terminate the application. ## Details When processing an `IdList` range, the reconciliation parser uses the peer-provided ID count to reserve memory before checking whether the message contains the corresponding IDs: ```rust let mut their_elems: HashSet = HashSet::with_capacity(num_ids as usize); ``` An attacker can declare an arbitrarily large count without supplying any IDs. The allocation occurs before the parser reaches the ID-reading loop, which would otherwise reject the truncated message. With Rust's default allocation-error behavior, a failed allocation aborts the process rather than unwinding. Consequently, `catch_unwind` cannot contain the failure. Both `reconcile` and `reconcile_with_ids` reach the vulnerable parser. The patched versions validate the count against the remaining message length before allocating: ```rust if num_ids > (query.len() / ID_SIZE) as u64 { return Err(Error::ParseEndsPrematurely); } ``` ## Impact An unauthenticated remote attacker can terminate an application that exposes reconciliation to untrusted peers without additional validation. For example, a Nostr relay that forwards `NEG-OPEN` or `NEG-MSG` reconciliation payloads to the vulnerable parser can be taken do",
    "evidence": "osv:RUSTSEC-2026-0365",
    "products": [
      {
        "name": {
          "value": "negentropy",
          "evidence": "/affected/0/package/name"
        },
        "prerequisites": [],
        "fixed_versions": [
          {
            "value": "0.4.4",
            "evidence": "/affected/0/ranges"
          },
          {
            "value": "0.5.2",
            "evidence": "/affected/0/ranges"
          }
        ],
        "affected_versions": []
      }
    ],
    "severity": "high",
    "structured": {
      "id": "RUSTSEC-2026-0365",
      "aliases": [
        "RUSTSEC-2026-0365"
      ],
      "metrics": [
        {
          "type": "CVSS_V3",
          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "type": "SEMVER",
              "events": [
                {
                  "introduced": "0.2.0"
                },
                {
                  "fixed": "0.4.4"
                },
                {
                  "introduced": "0.5.0"
                },
                {
                  "fixed": "0.5.2"
                }
              ]
            }
          ],
          "package": {
            "name": "negentropy",
            "purl": "pkg:cargo/negentropy",
            "ecosystem": "crates.io"
          },
          "database_specific": {
            "cvss": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
            "source": "https://github.com/rustsec/advisory-db/blob/osv/crates/RUSTSEC-2026-0365.json",
            "categories": [
              "denial-of-service"
            ],
            "informational": null
          },
          "ecosystem_specific": {
            "affects": {
              "os": [],
              "arch": [],
              "functions": []
            },
            "affected_functions": null
          }
        }
      ],
      "modified": "2026-10-16T23:30:02.383532013Z",
      "provider": "osv",
      "references": [
        "https://crates.io/crates/negentropy",
        "https://rustsec.org/advisories/RUSTSEC-2026-0365.html",
        "https://github.com/nostrdevkit/negentropy/pull/14",
        "https://github.com/nostrdevkit/negentropy/commit/40f7290cbc5755a5ba3190279fbc848a97866280",
        "https://github.com/nostrdevkit/negentropy/commit/894a32c0ab9f3efd750b3cf06caee27b3f9c3f12"
      ],
      "provider_metadata": {
        "license": "CC0-1.0"
      }
    },
    "related_cves": [],
    "security_relevant": true,
    "severity_evidence": "/severity/0/score"
  },
  "source_id": "core-osv",
  "document_id": 349389,
  "published_at": "2026-10-14T12:00:00+00:00"
}