{"id":"CVE-2026-113431","title":"Unbounded decoded HTTP/2 header-list size in cowlib cow_http2_machine enables HPACK amplification memory exhaustion","summary":"Allocation of Resources Without Limits or Throttling vulnerability in ninenines cowlib allows an unauthenticated remote peer to exhaust the memory of an HTTP/2 endpoint via HPACK-indexed header fields.\n\ncow_http2_machine:headers_decode/4…","severity":"high","cvss":8.7,"cvssVector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N","cvssSource":"cna","cwe":["CWE-770"],"vendor":"ninenines","product":"cowlib","affected":["cowlib >= 2.7.0 < *","ninenines/cowlib >= b461b119e78e4e09bb28b186b09da7ed4a86a0dd < a3b15e29b3067644bfd580246c87f7af7a90b3b8"],"published":"2026-11-06","updated":"2026-11-06","sourceUpdated":"2026-11-06T10:28:15.837Z","source":"CVEORG","sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-113431","references":[{"url":"https://cna.erlef.org/cves/CVE-2026-113431.html","label":"EEF CNA record for CVE-2026-113431"},{"url":"https://osv.dev/vulnerability/EEF-CVE-2026-113431","label":"OSV record EEF-CVE-2026-113431"},{"url":"https://github.com/ninenines/cowlib/commit/b461b119e78e4e09bb28b186b09da7ed4a86a0dd","label":"Introducing commit b461b11 in ninenines/cowlib"},{"url":"https://github.com/ninenines/cowlib/commit/a3b15e29b3067644bfd580246c87f7af7a90b3b8","label":"Fix commit a3b15e2 in ninenines/cowlib"}],"tags":["cve.org"],"ingestedAt":"2026-11-06T10:49:35.342Z","slug":"CVE-2026-113431","body":"## Overview\n\nAllocation of Resources Without Limits or Throttling vulnerability in ninenines cowlib allows an unauthenticated remote peer to exhaust the memory of an HTTP/2 endpoint via HPACK-indexed header fields.\n\ncow_http2_machine:headers_decode/4 in src/cow_http2_machine.erl decodes every HEADERS block with cow_hpack:decode/3. It bounds the compressed block size and the number of fields, but not the size of the decoded header list that RFC 9113 section 6.5.2 places under SETTINGS_MAX_HEADER_LIST_SIZE. A peer stores one header value of up to the dynamic table size (4096 bytes by default) and then references it with one-byte indexed fields, so about 100 bytes on the wire decode to a header list of about 390 KB. A consumer that copies the decoded values, as Cowboy does when cowboy_http2:headers_to_map/2 joins repeated cookie fields into one binary, allocates that amount for every stream. The total across streams and connections is not bounded.\n\nThis issue affects cowlib: from 2.7.0 onward.\n\n## Affected\n\n- `cowlib >= 2.7.0 < *`\n- `ninenines/cowlib >= b461b119e78e4e09bb28b186b09da7ed4a86a0dd < a3b15e29b3067644bfd580246c87f7af7a90b3b8`\n\n## Remediation\n\nRefer to the linked advisories for vendor-supplied fixes and affected version ranges.\n\n### Workarounds\n\nCowboy servers that do not need HTTP/2 can set protocols => [http] in the protocol options. The listener then answers the HTTP/2 preface with 501 Not Implemented and the decoder is never reached.\n\nLowering max_headers in the HTTP/2 protocol options shrinks the per-stream allocation in proportion, to about max_headers times the 4096-byte table entry. This reduces the amplification but does not remove it.","depth":"twilight","depthScore":48,"depthScoreParts":{"impact":47.8,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}