CVE-2026-97200 (GCVE-0-2026-97200)
Vulnerability from cvelistv5 – Published: 2026-10-26 13:49 – Updated: 2026-10-26 15:35
VLAI
EPSS
VEX
Title
Unbounded response body buffering and decompression in hackney
Summary
Allocation of Resources Without Limits or Throttling vulnerability in hackney_conn in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. hackney:request/5 and hackney:body/1 return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.
hackney_conn:read_full_body/2 and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With {auto_decompress, true} the buffered body is then inflated in one step with zlib:gunzip/1 or zlib:inflate/2, which return the whole output at once.
This issue affects hackney: from 2.0.0-beta.1 before 4.9.0.
Severity
SSVC
Exploitation: none
Automatable: yes
Technical Impact: partial
CISA Coordinator · CISA-ADP (v2.0.3)
Decision recorded 2026-10-26 14:54 UTC
CWE
Assigner
References
6 references
| URL | Tags |
|---|---|
| https://github.com/benoitc/hackney/releases/tag/4.9.0 | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-97200.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-97200 | related |
| https://github.com/benoitc/hackney/pull/980 | related |
| https://github.com/benoitc/hackney/commit/dc41b79… | related |
| https://github.com/benoitc/hackney/commit/493e8bf… | patch |
Impacted products
2 products
Date Public
2026-10-25 00:00
{
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-97200",
"options": [
{
"Exploitation": "none"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T14:54:57.385457Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T15:35:50.487Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"hackney_conn",
"hackney"
],
"packageName": "hackney",
"packageURL": "pkg:hex/hackney",
"product": "hackney",
"programFiles": [
"src/hackney_conn.erl",
"src/hackney.erl"
],
"programRoutines": [
{
"name": "hackney_conn:read_full_body/2"
},
{
"name": "hackney_conn:maybe_decompress_body/2"
},
{
"name": "hackney_conn:decompress_gzip/1"
},
{
"name": "hackney_conn:decompress_deflate/1"
},
{
"name": "hackney:request/5"
},
{
"name": "hackney:body/1"
}
],
"repo": "https://github.com/benoitc/hackney",
"vendor": "benoitc",
"versions": [
{
"lessThan": "4.9.0",
"status": "affected",
"version": "2.0.0-beta.1",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"hackney_conn",
"hackney"
],
"packageName": "benoitc/hackney",
"packageURL": "pkg:github/benoitc/hackney",
"product": "hackney",
"programFiles": [
"src/hackney_conn.erl",
"src/hackney.erl"
],
"programRoutines": [
{
"name": "hackney_conn:read_full_body/2"
},
{
"name": "hackney_conn:maybe_decompress_body/2"
},
{
"name": "hackney_conn:decompress_gzip/1"
},
{
"name": "hackney_conn:decompress_deflate/1"
},
{
"name": "hackney:request/5"
},
{
"name": "hackney:body/1"
}
],
"repo": "https://github.com/benoitc/hackney",
"vendor": "benoitc",
"versions": [
{
"lessThan": "493e8bf83a391548e5101792276ab3fc428fa76c",
"status": "affected",
"version": "dc41b79339ca0c41e16d3f2dd17172bc2de855d6",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*",
"versionEndExcluding": "4.9.0",
"versionStartIncluding": "2.0.0-beta.1",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Martin Karrer"
},
{
"lang": "en",
"type": "finder",
"value": "Quinn Wilton"
},
{
"lang": "en",
"type": "reporter",
"value": "Quinn Wilton"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Martin Karrer"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Benoit Chesneau"
},
{
"lang": "en",
"type": "coordinator",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"dateAssigned": "2026-10-26T09:42:31.000Z",
"datePublic": "2026-10-25T00:00:00.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAllocation of Resources Without Limits or Throttling vulnerability in \u003ccode\u003ehackney_conn\u003c/code\u003e in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. \u003ccode\u003ehackney:request/5\u003c/code\u003e and \u003ccode\u003ehackney:body/1\u003c/code\u003e return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehackney_conn:read_full_body/2\u003c/code\u003e and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With \u003ccode\u003e{auto_decompress, true}\u003c/code\u003e the buffered body is then inflated in one step with \u003ccode\u003ezlib:gunzip/1\u003c/code\u003e or \u003ccode\u003ezlib:inflate/2\u003c/code\u003e, which return the whole output at once.\u003c/p\u003e\n\u003cp\u003eThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Allocation of Resources Without Limits or Throttling vulnerability in `hackney_conn` in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. `hackney:request/5` and `hackney:body/1` return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\n\n`hackney_conn:read_full_body/2` and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With `{auto_decompress, true}` the buffered body is then inflated in one step with `zlib:gunzip/1` or `zlib:inflate/2`, which return the whole output at once.\n\nThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0."
}
],
"value": "Allocation of Resources Without Limits or Throttling vulnerability in hackney_conn in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. hackney:request/5 and hackney:body/1 return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\n\nhackney_conn:read_full_body/2 and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With {auto_decompress, true} the buffered body is then inflated in one step with zlib:gunzip/1 or zlib:inflate/2, which return the whole output at once.\n\nThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eA server the client requests can make the client allocate memory proportional to the body it sends, or to its decompressed size, until the node runs out of memory.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "A server the client requests can make the client allocate memory proportional to the body it sends, or to its decompressed size, until the node runs out of memory."
}
],
"value": "A server the client requests can make the client allocate memory proportional to the body it sends, or to its decompressed size, until the node runs out of memory."
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "NETWORK",
"baseScore": 8.2,
"baseSeverity": "HIGH",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-409",
"description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
"lang": "en",
"type": "CWE"
}
]
},
{
"descriptions": [
{
"cweId": "CWE-770",
"description": "CWE-770 Allocation of Resources Without Limits or Throttling",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T13:49:40.392Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "hackney 4.9.0 release notes",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/benoitc/hackney/releases/tag/4.9.0"
},
{
"name": "EEF CNA record for CVE-2026-97200",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-97200.html"
},
{
"name": "OSV record EEF-CVE-2026-97200",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-97200"
},
{
"name": "Cap buffered response bodies with max_body_size and bound decompression (benoitc/hackney#980)",
"tags": [
"related"
],
"url": "https://github.com/benoitc/hackney/pull/980"
},
{
"name": "Introducing commit dc41b79 in benoitc/hackney",
"tags": [
"related"
],
"url": "https://github.com/benoitc/hackney/commit/dc41b79339ca0c41e16d3f2dd17172bc2de855d6"
},
{
"name": "Fix commit 493e8bf in benoitc/hackney",
"tags": [
"patch"
],
"url": "https://github.com/benoitc/hackney/commit/493e8bf83a391548e5101792276ab3fc428fa76c"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Unbounded response body buffering and decompression in hackney",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eLeave \u003ccode\u003eauto_decompress\u003c/code\u003e disabled (the default). Without it \u003ccode\u003ehackney_conn:maybe_decompress_body/2\u003c/code\u003e never inflates the body, which closes the amplification half. The uncapped raw body read has no workaround.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Leave `auto_decompress` disabled (the default). Without it `hackney_conn:maybe_decompress_body/2` never inflates the body, which closes the amplification half. The uncapped raw body read has no workaround."
}
],
"value": "Leave auto_decompress disabled (the default). Without it hackney_conn:maybe_decompress_body/2 never inflates the body, which closes the amplification half. The uncapped raw body read has no workaround."
}
],
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eBuild a gzip stream whose inflated size is 1 GB from a reused 64 KB chunk of zero bytes (deflate with window bits 31, best compression). The stream is about 1 MB on the wire.\u003c/li\u003e\n\u003cli\u003eStart a TCP listener on loopback that accepts one connection, reads the request, and answers \u003ccode\u003eHTTP/1.1 200 OK\u003c/code\u003e with \u003ccode\u003eContent-Encoding: gzip\u003c/code\u003e, a \u003ccode\u003eContent-Length\u003c/code\u003e matching the stream, \u003ccode\u003eConnection: close\u003c/code\u003e, and the stream as body.\u003c/li\u003e\n\u003cli\u003eFrom a node running a vulnerable hackney, call \u003ccode\u003ehackney:request(get, Url, [], \u0026lt;\u0026lt;\u0026gt;\u0026gt;, [{auto_decompress, true}, with_body])\u003c/code\u003e against that listener.\u003c/li\u003e\n\u003cli\u003eObserve the returned body of 1,048,576,000 bytes and the VM memory growing by about 1.8 GB for a 1,019,197 byte response. A larger stream, or an endless body without \u003ccode\u003eauto_decompress\u003c/code\u003e, drives the node out of memory.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. Build a gzip stream whose inflated size is 1 GB from a reused 64 KB chunk of zero bytes (deflate with window bits 31, best compression). The stream is about 1 MB on the wire.\n2. Start a TCP listener on loopback that accepts one connection, reads the request, and answers `HTTP/1.1 200 OK` with `Content-Encoding: gzip`, a `Content-Length` matching the stream, `Connection: close`, and the stream as body.\n3. From a node running a vulnerable hackney, call `hackney:request(get, Url, [], \u003c\u003c\u003e\u003e, [{auto_decompress, true}, with_body])` against that listener.\n4. Observe the returned body of 1,048,576,000 bytes and the VM memory growing by about 1.8 GB for a 1,019,197 byte response. A larger stream, or an endless body without `auto_decompress`, drives the node out of memory."
}
],
"value": "* Build a gzip stream whose inflated size is 1 GB from a reused 64 KB chunk of zero bytes (deflate with window bits 31, best compression). The stream is about 1 MB on the wire.\n* Start a TCP listener on loopback that accepts one connection, reads the request, and answers HTTP/1.1 200 OK with Content-Encoding: gzip, a Content-Length matching the stream, Connection: close, and the stream as body.\n* From a node running a vulnerable hackney, call hackney:request(get, Url, [], \u003c\u003c\u003e\u003e, [{auto_decompress, true}, with_body]) against that listener.\n* Observe the returned body of 1,048,576,000 bytes and the VM memory growing by about 1.8 GB for a 1,019,197 byte response. A larger stream, or an endless body without auto_decompress, drives the node out of memory."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Unbounded accumulation.\u003c/strong\u003e \u003ccode\u003ehackney:request/5\u003c/code\u003e with a body, and \u003ccode\u003ehackney:body/1\u003c/code\u003e after \u003ccode\u003estart_response/1\u003c/code\u003e, read the response in \u003ccode\u003esrc/hackney_conn.erl\u003c/code\u003e through \u003ccode\u003eread_full_body/2\u003c/code\u003e, which appends each chunk to a binary accumulator until the body ends. The HTTP/2 and HTTP/3 synchronous paths accumulate stream data the same way. No option caps the size.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. One-step decompression.\u003c/strong\u003e With \u003ccode\u003e{auto_decompress, true}\u003c/code\u003e hackney sends \u003ccode\u003eAccept-Encoding: gzip, deflate\u003c/code\u003e. Once the body is complete, \u003ccode\u003emaybe_decompress_body/2\u003c/code\u003e dispatches on \u003ccode\u003eContent-Encoding\u003c/code\u003e to \u003ccode\u003edecompress_gzip/1\u003c/code\u003e (\u003ccode\u003ezlib:gunzip/1\u003c/code\u003e) or \u003ccode\u003edecompress_deflate/1\u003c/code\u003e (\u003ccode\u003ezlib:inflate/2\u003c/code\u003e). Both return the whole output at once, so the inflated size is bounded only by the compression ratio. The report measured a 1 MB gzip body inflating to 1 GB on hackney 4.8.4.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Unbounded accumulation.** `hackney:request/5` with a body, and `hackney:body/1` after `start_response/1`, read the response in `src/hackney_conn.erl` through `read_full_body/2`, which appends each chunk to a binary accumulator until the body ends. The HTTP/2 and HTTP/3 synchronous paths accumulate stream data the same way. No option caps the size.\n\n**2. One-step decompression.** With `{auto_decompress, true}` hackney sends `Accept-Encoding: gzip, deflate`. Once the body is complete, `maybe_decompress_body/2` dispatches on `Content-Encoding` to `decompress_gzip/1` (`zlib:gunzip/1`) or `decompress_deflate/1` (`zlib:inflate/2`). Both return the whole output at once, so the inflated size is bounded only by the compression ratio. The report measured a 1 MB gzip body inflating to 1 GB on hackney 4.8.4."
}
],
"value": "1. Unbounded accumulation. hackney:request/5 with a body, and hackney:body/1 after start_response/1, read the response in src/hackney_conn.erl through read_full_body/2, which appends each chunk to a binary accumulator until the body ends. The HTTP/2 and HTTP/3 synchronous paths accumulate stream data the same way. No option caps the size.\n\n2. One-step decompression. With {auto_decompress, true} hackney sends Accept-Encoding: gzip, deflate. Once the body is complete, maybe_decompress_body/2 dispatches on Content-Encoding to decompress_gzip/1 (zlib:gunzip/1) or decompress_deflate/1 (zlib:inflate/2). Both return the whole output at once, so the inflated size is bounded only by the compression ratio. The report measured a 1 MB gzip body inflating to 1 GB on hackney 4.8.4."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-97200",
"datePublished": "2026-10-26T13:49:40.392Z",
"dateReserved": "2026-10-26T05:15:01.465Z",
"dateUpdated": "2026-10-26T15:35:50.487Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"epss": {
"cve": "CVE-2026-97200",
"date": "2026-10-28",
"epss": "0.00564",
"percentile": "0.46739"
},
"nvd": {
"cve": {
"affected": [
{
"affectedData": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"hackney_conn",
"hackney"
],
"packageName": "hackney",
"packageURL": "pkg:hex/hackney",
"product": "hackney",
"programFiles": [
"src/hackney_conn.erl",
"src/hackney.erl"
],
"programRoutines": [
{
"name": "hackney_conn:read_full_body/2"
},
{
"name": "hackney_conn:maybe_decompress_body/2"
},
{
"name": "hackney_conn:decompress_gzip/1"
},
{
"name": "hackney_conn:decompress_deflate/1"
},
{
"name": "hackney:request/5"
},
{
"name": "hackney:body/1"
}
],
"repo": "https://github.com/benoitc/hackney",
"vendor": "benoitc",
"versions": [
{
"lessThan": "4.9.0",
"status": "affected",
"version": "2.0.0-beta.1",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"hackney_conn",
"hackney"
],
"packageName": "benoitc/hackney",
"packageURL": "pkg:github/benoitc/hackney",
"product": "hackney",
"programFiles": [
"src/hackney_conn.erl",
"src/hackney.erl"
],
"programRoutines": [
{
"name": "hackney_conn:read_full_body/2"
},
{
"name": "hackney_conn:maybe_decompress_body/2"
},
{
"name": "hackney_conn:decompress_gzip/1"
},
{
"name": "hackney_conn:decompress_deflate/1"
},
{
"name": "hackney:request/5"
},
{
"name": "hackney:body/1"
}
],
"repo": "https://github.com/benoitc/hackney",
"vendor": "benoitc",
"versions": [
{
"lessThan": "493e8bf83a391548e5101792276ab3fc428fa76c",
"status": "affected",
"version": "dc41b79339ca0c41e16d3f2dd17172bc2de855d6",
"versionType": "git"
}
]
}
],
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db"
}
],
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "Allocation of Resources Without Limits or Throttling vulnerability in hackney_conn in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. hackney:request/5 and hackney:body/1 return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\n\nhackney_conn:read_full_body/2 and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With {auto_decompress, true} the buffered body is then inflated in one step with zlib:gunzip/1 or zlib:inflate/2, which return the whole output at once.\n\nThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0."
}
],
"id": "CVE-2026-97200",
"lastModified": "2026-10-26T16:59:16.113",
"metrics": {
"cvssMetricV40": [
{
"cvssData": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "NETWORK",
"availabilityRequirement": "NOT_DEFINED",
"baseScore": 8.2,
"baseSeverity": "HIGH",
"confidentialityRequirement": "NOT_DEFINED",
"exploitMaturity": "NOT_DEFINED",
"integrityRequirement": "NOT_DEFINED",
"modifiedAttackComplexity": "NOT_DEFINED",
"modifiedAttackRequirements": "NOT_DEFINED",
"modifiedAttackVector": "NOT_DEFINED",
"modifiedPrivilegesRequired": "NOT_DEFINED",
"modifiedSubAvailabilityImpact": "NOT_DEFINED",
"modifiedSubConfidentialityImpact": "NOT_DEFINED",
"modifiedSubIntegrityImpact": "NOT_DEFINED",
"modifiedUserInteraction": "NOT_DEFINED",
"modifiedVulnAvailabilityImpact": "NOT_DEFINED",
"modifiedVulnConfidentialityImpact": "NOT_DEFINED",
"modifiedVulnIntegrityImpact": "NOT_DEFINED",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"type": "Secondary"
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"id": "CVE-2026-97200",
"options": [
{
"exploitation": "none"
},
{
"automatable": "yes"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T14:54:57.385457Z",
"version": "2.0.3"
}
}
]
},
"published": "2026-10-26T14:16:42.180",
"references": [
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://cna.erlef.org/cves/CVE-2026-97200.html"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/benoitc/hackney/commit/493e8bf83a391548e5101792276ab3fc428fa76c"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/benoitc/hackney/commit/dc41b79339ca0c41e16d3f2dd17172bc2de855d6"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/benoitc/hackney/pull/980"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/benoitc/hackney/releases/tag/4.9.0"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-97200"
}
],
"sourceIdentifier": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"vulnStatus": "Awaiting Analysis",
"weaknesses": [
{
"description": [
{
"lang": "en",
"value": "CWE-409"
},
{
"lang": "en",
"value": "CWE-770"
}
],
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"type": "Secondary"
}
]
}
},
"vulnrichment": {
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-97200",
"options": [
{
"Exploitation": "none"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T14:54:57.385457Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T15:32:12.835Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"hackney_conn",
"hackney"
],
"packageName": "hackney",
"packageURL": "pkg:hex/hackney",
"product": "hackney",
"programFiles": [
"src/hackney_conn.erl",
"src/hackney.erl"
],
"programRoutines": [
{
"name": "hackney_conn:read_full_body/2"
},
{
"name": "hackney_conn:maybe_decompress_body/2"
},
{
"name": "hackney_conn:decompress_gzip/1"
},
{
"name": "hackney_conn:decompress_deflate/1"
},
{
"name": "hackney:request/5"
},
{
"name": "hackney:body/1"
}
],
"repo": "https://github.com/benoitc/hackney",
"vendor": "benoitc",
"versions": [
{
"lessThan": "4.9.0",
"status": "affected",
"version": "2.0.0-beta.1",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"hackney_conn",
"hackney"
],
"packageName": "benoitc/hackney",
"packageURL": "pkg:github/benoitc/hackney",
"product": "hackney",
"programFiles": [
"src/hackney_conn.erl",
"src/hackney.erl"
],
"programRoutines": [
{
"name": "hackney_conn:read_full_body/2"
},
{
"name": "hackney_conn:maybe_decompress_body/2"
},
{
"name": "hackney_conn:decompress_gzip/1"
},
{
"name": "hackney_conn:decompress_deflate/1"
},
{
"name": "hackney:request/5"
},
{
"name": "hackney:body/1"
}
],
"repo": "https://github.com/benoitc/hackney",
"vendor": "benoitc",
"versions": [
{
"lessThan": "493e8bf83a391548e5101792276ab3fc428fa76c",
"status": "affected",
"version": "dc41b79339ca0c41e16d3f2dd17172bc2de855d6",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:*",
"versionEndExcluding": "4.9.0",
"versionStartIncluding": "2.0.0-beta.1",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Martin Karrer"
},
{
"lang": "en",
"type": "finder",
"value": "Quinn Wilton"
},
{
"lang": "en",
"type": "reporter",
"value": "Quinn Wilton"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Martin Karrer"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Benoit Chesneau"
},
{
"lang": "en",
"type": "coordinator",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"dateAssigned": "2026-10-26T09:42:31.000Z",
"datePublic": "2026-10-25T00:00:00.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAllocation of Resources Without Limits or Throttling vulnerability in \u003ccode\u003ehackney_conn\u003c/code\u003e in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. \u003ccode\u003ehackney:request/5\u003c/code\u003e and \u003ccode\u003ehackney:body/1\u003c/code\u003e return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehackney_conn:read_full_body/2\u003c/code\u003e and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With \u003ccode\u003e{auto_decompress, true}\u003c/code\u003e the buffered body is then inflated in one step with \u003ccode\u003ezlib:gunzip/1\u003c/code\u003e or \u003ccode\u003ezlib:inflate/2\u003c/code\u003e, which return the whole output at once.\u003c/p\u003e\n\u003cp\u003eThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Allocation of Resources Without Limits or Throttling vulnerability in `hackney_conn` in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. `hackney:request/5` and `hackney:body/1` return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\n\n`hackney_conn:read_full_body/2` and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With `{auto_decompress, true}` the buffered body is then inflated in one step with `zlib:gunzip/1` or `zlib:inflate/2`, which return the whole output at once.\n\nThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0."
}
],
"value": "Allocation of Resources Without Limits or Throttling vulnerability in hackney_conn in benoitc hackney allows a malicious HTTP server to exhaust client memory via an oversized or highly compressed response body. hackney:request/5 and hackney:body/1 return the whole response body, and nothing bounds how much the connection process buffers. Any server the client requests can trigger it.\n\nhackney_conn:read_full_body/2 and the HTTP/2 and HTTP/3 accumulators append every chunk until the body ends. With {auto_decompress, true} the buffered body is then inflated in one step with zlib:gunzip/1 or zlib:inflate/2, which return the whole output at once.\n\nThis issue affects hackney: from 2.0.0-beta.1 before 4.9.0."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eA server the client requests can make the client allocate memory proportional to the body it sends, or to its decompressed size, until the node runs out of memory.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "A server the client requests can make the client allocate memory proportional to the body it sends, or to its decompressed size, until the node runs out of memory."
}
],
"value": "A server the client requests can make the client allocate memory proportional to the body it sends, or to its decompressed size, until the node runs out of memory."
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "NETWORK",
"baseScore": 8.2,
"baseSeverity": "HIGH",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-409",
"description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
"lang": "en",
"type": "CWE"
}
]
},
{
"descriptions": [
{
"cweId": "CWE-770",
"description": "CWE-770 Allocation of Resources Without Limits or Throttling",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T13:49:40.392Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "hackney 4.9.0 release notes",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/benoitc/hackney/releases/tag/4.9.0"
},
{
"name": "EEF CNA record for CVE-2026-97200",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-97200.html"
},
{
"name": "OSV record EEF-CVE-2026-97200",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-97200"
},
{
"name": "Cap buffered response bodies with max_body_size and bound decompression (benoitc/hackney#980)",
"tags": [
"related"
],
"url": "https://github.com/benoitc/hackney/pull/980"
},
{
"name": "Introducing commit dc41b79 in benoitc/hackney",
"tags": [
"related"
],
"url": "https://github.com/benoitc/hackney/commit/dc41b79339ca0c41e16d3f2dd17172bc2de855d6"
},
{
"name": "Fix commit 493e8bf in benoitc/hackney",
"tags": [
"patch"
],
"url": "https://github.com/benoitc/hackney/commit/493e8bf83a391548e5101792276ab3fc428fa76c"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Unbounded response body buffering and decompression in hackney",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eLeave \u003ccode\u003eauto_decompress\u003c/code\u003e disabled (the default). Without it \u003ccode\u003ehackney_conn:maybe_decompress_body/2\u003c/code\u003e never inflates the body, which closes the amplification half. The uncapped raw body read has no workaround.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Leave `auto_decompress` disabled (the default). Without it `hackney_conn:maybe_decompress_body/2` never inflates the body, which closes the amplification half. The uncapped raw body read has no workaround."
}
],
"value": "Leave auto_decompress disabled (the default). Without it hackney_conn:maybe_decompress_body/2 never inflates the body, which closes the amplification half. The uncapped raw body read has no workaround."
}
],
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eBuild a gzip stream whose inflated size is 1 GB from a reused 64 KB chunk of zero bytes (deflate with window bits 31, best compression). The stream is about 1 MB on the wire.\u003c/li\u003e\n\u003cli\u003eStart a TCP listener on loopback that accepts one connection, reads the request, and answers \u003ccode\u003eHTTP/1.1 200 OK\u003c/code\u003e with \u003ccode\u003eContent-Encoding: gzip\u003c/code\u003e, a \u003ccode\u003eContent-Length\u003c/code\u003e matching the stream, \u003ccode\u003eConnection: close\u003c/code\u003e, and the stream as body.\u003c/li\u003e\n\u003cli\u003eFrom a node running a vulnerable hackney, call \u003ccode\u003ehackney:request(get, Url, [], \u0026lt;\u0026lt;\u0026gt;\u0026gt;, [{auto_decompress, true}, with_body])\u003c/code\u003e against that listener.\u003c/li\u003e\n\u003cli\u003eObserve the returned body of 1,048,576,000 bytes and the VM memory growing by about 1.8 GB for a 1,019,197 byte response. A larger stream, or an endless body without \u003ccode\u003eauto_decompress\u003c/code\u003e, drives the node out of memory.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. Build a gzip stream whose inflated size is 1 GB from a reused 64 KB chunk of zero bytes (deflate with window bits 31, best compression). The stream is about 1 MB on the wire.\n2. Start a TCP listener on loopback that accepts one connection, reads the request, and answers `HTTP/1.1 200 OK` with `Content-Encoding: gzip`, a `Content-Length` matching the stream, `Connection: close`, and the stream as body.\n3. From a node running a vulnerable hackney, call `hackney:request(get, Url, [], \u003c\u003c\u003e\u003e, [{auto_decompress, true}, with_body])` against that listener.\n4. Observe the returned body of 1,048,576,000 bytes and the VM memory growing by about 1.8 GB for a 1,019,197 byte response. A larger stream, or an endless body without `auto_decompress`, drives the node out of memory."
}
],
"value": "* Build a gzip stream whose inflated size is 1 GB from a reused 64 KB chunk of zero bytes (deflate with window bits 31, best compression). The stream is about 1 MB on the wire.\n* Start a TCP listener on loopback that accepts one connection, reads the request, and answers HTTP/1.1 200 OK with Content-Encoding: gzip, a Content-Length matching the stream, Connection: close, and the stream as body.\n* From a node running a vulnerable hackney, call hackney:request(get, Url, [], \u003c\u003c\u003e\u003e, [{auto_decompress, true}, with_body]) against that listener.\n* Observe the returned body of 1,048,576,000 bytes and the VM memory growing by about 1.8 GB for a 1,019,197 byte response. A larger stream, or an endless body without auto_decompress, drives the node out of memory."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Unbounded accumulation.\u003c/strong\u003e \u003ccode\u003ehackney:request/5\u003c/code\u003e with a body, and \u003ccode\u003ehackney:body/1\u003c/code\u003e after \u003ccode\u003estart_response/1\u003c/code\u003e, read the response in \u003ccode\u003esrc/hackney_conn.erl\u003c/code\u003e through \u003ccode\u003eread_full_body/2\u003c/code\u003e, which appends each chunk to a binary accumulator until the body ends. The HTTP/2 and HTTP/3 synchronous paths accumulate stream data the same way. No option caps the size.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. One-step decompression.\u003c/strong\u003e With \u003ccode\u003e{auto_decompress, true}\u003c/code\u003e hackney sends \u003ccode\u003eAccept-Encoding: gzip, deflate\u003c/code\u003e. Once the body is complete, \u003ccode\u003emaybe_decompress_body/2\u003c/code\u003e dispatches on \u003ccode\u003eContent-Encoding\u003c/code\u003e to \u003ccode\u003edecompress_gzip/1\u003c/code\u003e (\u003ccode\u003ezlib:gunzip/1\u003c/code\u003e) or \u003ccode\u003edecompress_deflate/1\u003c/code\u003e (\u003ccode\u003ezlib:inflate/2\u003c/code\u003e). Both return the whole output at once, so the inflated size is bounded only by the compression ratio. The report measured a 1 MB gzip body inflating to 1 GB on hackney 4.8.4.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Unbounded accumulation.** `hackney:request/5` with a body, and `hackney:body/1` after `start_response/1`, read the response in `src/hackney_conn.erl` through `read_full_body/2`, which appends each chunk to a binary accumulator until the body ends. The HTTP/2 and HTTP/3 synchronous paths accumulate stream data the same way. No option caps the size.\n\n**2. One-step decompression.** With `{auto_decompress, true}` hackney sends `Accept-Encoding: gzip, deflate`. Once the body is complete, `maybe_decompress_body/2` dispatches on `Content-Encoding` to `decompress_gzip/1` (`zlib:gunzip/1`) or `decompress_deflate/1` (`zlib:inflate/2`). Both return the whole output at once, so the inflated size is bounded only by the compression ratio. The report measured a 1 MB gzip body inflating to 1 GB on hackney 4.8.4."
}
],
"value": "1. Unbounded accumulation. hackney:request/5 with a body, and hackney:body/1 after start_response/1, read the response in src/hackney_conn.erl through read_full_body/2, which appends each chunk to a binary accumulator until the body ends. The HTTP/2 and HTTP/3 synchronous paths accumulate stream data the same way. No option caps the size.\n\n2. One-step decompression. With {auto_decompress, true} hackney sends Accept-Encoding: gzip, deflate. Once the body is complete, maybe_decompress_body/2 dispatches on Content-Encoding to decompress_gzip/1 (zlib:gunzip/1) or decompress_deflate/1 (zlib:inflate/2). Both return the whole output at once, so the inflated size is bounded only by the compression ratio. The report measured a 1 MB gzip body inflating to 1 GB on hackney 4.8.4."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-97200",
"datePublished": "2026-10-26T13:49:40.392Z",
"dateReserved": "2026-10-26T05:15:01.465Z",
"dateUpdated": "2026-10-26T15:35:50.487Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
}
}
Loading…
Loading…
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
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.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
Loading…
Loading…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Loading…
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.