CVE-2026-113436 (GCVE-0-2026-113436)
Vulnerability from cvelistv5 – Published: 2026-10-26 13:31 – Updated: 2026-10-26 15:35- CWE-407 - Inefficient Algorithmic Complexity
| URL | Tags |
|---|---|
| https://github.com/mtrudel/bandit/security/adviso… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-113436.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-113436 | related |
| https://github.com/mtrudel/bandit/commit/e0c8c0c3… | related |
| https://github.com/mtrudel/bandit/commit/220b9dfd… | patch |
{
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-113436",
"options": [
{
"Exploitation": "none"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T15:12:04.626946Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T15:35:51.556Z",
"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:mtrudel:bandit:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"packageName": "bandit",
"packageURL": "pkg:hex/bandit",
"product": "bandit",
"repo": "https://github.com/mtrudel/bandit",
"vendor": "mtrudel",
"versions": [
{
"lessThan": "1.14.0",
"status": "affected",
"version": "1.0.0-pre.7",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"packageName": "mtrudel/bandit",
"packageURL": "pkg:github/mtrudel/bandit",
"product": "bandit",
"repo": "https://github.com/mtrudel/bandit",
"vendor": "mtrudel",
"versions": [
{
"lessThan": "220b9dfd27f9a21305be2afc75cbe585ddc24e7a",
"status": "affected",
"version": "e0c8c0c30af9b0f57d8aafac37ddd9294363a8be",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.14.0",
"versionStartIncluding": "1.0.0-pre.7",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Mat Trudel"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"dateAssigned": "2026-10-23T12:44:41.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eInefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a \u003ccode\u003econtent-length\u003c/code\u003e value or a \u003ccode\u003eHost\u003c/code\u003e or \u003ccode\u003e:authority\u003c/code\u003e port made of thousands of digits.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eBandit.Headers.parse_integer/2\u003c/code\u003e in \u003ccode\u003elib/bandit/headers.ex\u003c/code\u003e builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Inefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a `content-length` value or a `Host` or `:authority` port made of thousands of digits.\n\n`Bandit.Headers.parse_integer/2` in `lib/bandit/headers.ex` builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\n\nThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0."
}
],
"value": "Inefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a content-length value or a Host or :authority port made of thousands of digits.\n\nBandit.Headers.parse_integer/2 in lib/bandit/headers.ex builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\n\nThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAn unauthenticated client can make the server spend CPU time out of all proportion to the traffic it sends (27.9 s for 124 KB in the reporter\u0027s test). This affects any Bandit server reachable by untrusted clients over HTTP/1 or HTTP/2, with no special configuration.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "An unauthenticated client can make the server spend CPU time out of all proportion to the traffic it sends (27.9 s for 124 KB in the reporter\u0027s test). This affects any Bandit server reachable by untrusted clients over HTTP/1 or HTTP/2, with no special configuration."
}
],
"value": "An unauthenticated client can make the server spend CPU time out of all proportion to the traffic it sends (27.9 s for 124 KB in the reporter\u0027s test). This affects any Bandit server reachable by untrusted clients over HTTP/1 or HTTP/2, with no special configuration."
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"baseScore": 8.7,
"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:N/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-407",
"description": "CWE-407 Inefficient Algorithmic Complexity",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T13:31:35.033Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "Quadratic bignum parsing of Content-Length and Host port values in Bandit",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-29cr-8477-rg6r"
},
{
"name": "EEF CNA record for CVE-2026-113436",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-113436.html"
},
{
"name": "OSV record EEF-CVE-2026-113436",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-113436"
},
{
"name": "Introducing commit e0c8c0c in mtrudel/bandit",
"tags": [
"related"
],
"url": "https://github.com/mtrudel/bandit/commit/e0c8c0c30af9b0f57d8aafac37ddd9294363a8be"
},
{
"name": "Fix commit 220b9df in mtrudel/bandit",
"tags": [
"patch"
],
"url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
}
],
"source": {
"discovery": "UNKNOWN"
},
"title": "Quadratic bignum parsing of Content-Length and Host port values in Bandit",
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eRun Bandit with any Plug.\u003c/li\u003e\n\u003cli\u003eOpen an HTTP/2 connection with prior knowledge and complete the SETTINGS exchange.\u003c/li\u003e\n\u003cli\u003eIn one write, send 5,000 HEADERS frames for \u003ccode\u003ePOST /\u003c/code\u003e on new streams, each carrying a \u003ccode\u003econtent-length\u003c/code\u003e of 4,000 \u003ccode\u003e9\u003c/code\u003e digits encoded with HPACK indexing, so that every frame after the first refers to the stored value.\u003c/li\u003e\n\u003cli\u003eThe 124,003 bytes take 27.9 s to process before all 5,000 requests reach the Plug.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. Run Bandit with any Plug.\n2. Open an HTTP/2 connection with prior knowledge and complete the SETTINGS exchange.\n3. In one write, send 5,000 HEADERS frames for `POST /` on new streams, each carrying a `content-length` of 4,000 `9` digits encoded with HPACK indexing, so that every frame after the first refers to the stored value.\n4. The 124,003 bytes take 27.9 s to process before all 5,000 requests reach the Plug."
}
],
"value": "* Run Bandit with any Plug.\n* Open an HTTP/2 connection with prior knowledge and complete the SETTINGS exchange.\n* In one write, send 5,000 HEADERS frames for POST / on new streams, each carrying a content-length of 4,000 9 digits encoded with HPACK indexing, so that every frame after the first refers to the stored value.\n* The 124,003 bytes take 27.9 s to process before all 5,000 requests reach the Plug."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Unbounded digit loop.\u003c/strong\u003e \u003ccode\u003eBandit.Headers.parse_integer/2\u003c/code\u003e in \u003ccode\u003elib/bandit/headers.ex\u003c/code\u003e builds the number with \u003ccode\u003etotal * 10 + digit - ?0\u003c/code\u003e and has no limit on the digit count. Each step allocates a new bignum, so parsing one value costs O(n\u00b2). On OTP 28, 10,000 digits take about 10 ms, 50,000 about 250 ms and 80,000 about 560 ms, where \u003ccode\u003eString.to_integer/1\u003c/code\u003e handles the same inputs in 1 to 3 ms.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Reached on raw input.\u003c/strong\u003e It is called from \u003ccode\u003eget_content_length/1\u003c/code\u003e and \u003ccode\u003eparse_hostlike_header!/1\u003c/code\u003e on raw request input, before any range check. An all-digit \u003ccode\u003econtent-length\u003c/code\u003e is returned as \u003ccode\u003e{:ok, huge_int}\u003c/code\u003e, and the \u003ccode\u003eis_port_number\u003c/code\u003e guard only runs after the whole number is built.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. HPACK amplification.\u003c/strong\u003e Over HTTP/2, a 4,000-digit value (about 1.1 ms to parse) can be stored once in the HPACK dynamic table and then re-sent on each new stream for about one byte.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Unbounded digit loop.** `Bandit.Headers.parse_integer/2` in `lib/bandit/headers.ex` builds the number with `total * 10 + digit - ?0` and has no limit on the digit count. Each step allocates a new bignum, so parsing one value costs O(n\u00b2). On OTP 28, 10,000 digits take about 10 ms, 50,000 about 250 ms and 80,000 about 560 ms, where `String.to_integer/1` handles the same inputs in 1 to 3 ms.\n\n**2. Reached on raw input.** It is called from `get_content_length/1` and `parse_hostlike_header!/1` on raw request input, before any range check. An all-digit `content-length` is returned as `{:ok, huge_int}`, and the `is_port_number` guard only runs after the whole number is built.\n\n**3. HPACK amplification.** Over HTTP/2, a 4,000-digit value (about 1.1 ms to parse) can be stored once in the HPACK dynamic table and then re-sent on each new stream for about one byte."
}
],
"value": "1. Unbounded digit loop. Bandit.Headers.parse_integer/2 in lib/bandit/headers.ex builds the number with total * 10 + digit - ?0 and has no limit on the digit count. Each step allocates a new bignum, so parsing one value costs O(n\u00b2). On OTP 28, 10,000 digits take about 10 ms, 50,000 about 250 ms and 80,000 about 560 ms, where String.to_integer/1 handles the same inputs in 1 to 3 ms.\n\n2. Reached on raw input. It is called from get_content_length/1 and parse_hostlike_header!/1 on raw request input, before any range check. An all-digit content-length is returned as {:ok, huge_int}, and the is_port_number guard only runs after the whole number is built.\n\n3. HPACK amplification. Over HTTP/2, a 4,000-digit value (about 1.1 ms to parse) can be stored once in the HPACK dynamic table and then re-sent on each new stream for about one byte."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-113436",
"datePublished": "2026-10-26T13:31:35.033Z",
"dateReserved": "2026-10-23T10:30:01.881Z",
"dateUpdated": "2026-10-26T15:35:51.556Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"epss": {
"cve": "CVE-2026-113436",
"date": "2026-11-12",
"epss": "0.00602",
"percentile": "0.49331"
},
"nvd": {
"cve": {
"affected": [
{
"affectedData": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"packageName": "bandit",
"packageURL": "pkg:hex/bandit",
"product": "bandit",
"repo": "https://github.com/mtrudel/bandit",
"vendor": "mtrudel",
"versions": [
{
"lessThan": "1.14.0",
"status": "affected",
"version": "1.0.0-pre.7",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"packageName": "mtrudel/bandit",
"packageURL": "pkg:github/mtrudel/bandit",
"product": "bandit",
"repo": "https://github.com/mtrudel/bandit",
"vendor": "mtrudel",
"versions": [
{
"lessThan": "220b9dfd27f9a21305be2afc75cbe585ddc24e7a",
"status": "affected",
"version": "e0c8c0c30af9b0f57d8aafac37ddd9294363a8be",
"versionType": "git"
}
]
}
],
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db"
}
],
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "Inefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a content-length value or a Host or :authority port made of thousands of digits.\n\nBandit.Headers.parse_integer/2 in lib/bandit/headers.ex builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\n\nThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0."
}
],
"id": "CVE-2026-113436",
"lastModified": "2026-10-26T16:59:16.113",
"metrics": {
"cvssMetricV40": [
{
"cvssData": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"availabilityRequirement": "NOT_DEFINED",
"baseScore": 8.7,
"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:N/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-113436",
"options": [
{
"exploitation": "none"
},
{
"automatable": "yes"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T15:12:04.626946Z",
"version": "2.0.3"
}
}
]
},
"published": "2026-10-26T14:16:28.680",
"references": [
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://cna.erlef.org/cves/CVE-2026-113436.html"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/mtrudel/bandit/commit/e0c8c0c30af9b0f57d8aafac37ddd9294363a8be"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-29cr-8477-rg6r"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-113436"
}
],
"sourceIdentifier": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"vulnStatus": "Awaiting Analysis",
"weaknesses": [
{
"description": [
{
"lang": "en",
"value": "CWE-407"
}
],
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"type": "Secondary"
}
]
}
},
"vulnrichment": {
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-113436",
"options": [
{
"Exploitation": "none"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T15:12:04.626946Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T15:32:51.911Z",
"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:mtrudel:bandit:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"packageName": "bandit",
"packageURL": "pkg:hex/bandit",
"product": "bandit",
"repo": "https://github.com/mtrudel/bandit",
"vendor": "mtrudel",
"versions": [
{
"lessThan": "1.14.0",
"status": "affected",
"version": "1.0.0-pre.7",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"packageName": "mtrudel/bandit",
"packageURL": "pkg:github/mtrudel/bandit",
"product": "bandit",
"repo": "https://github.com/mtrudel/bandit",
"vendor": "mtrudel",
"versions": [
{
"lessThan": "220b9dfd27f9a21305be2afc75cbe585ddc24e7a",
"status": "affected",
"version": "e0c8c0c30af9b0f57d8aafac37ddd9294363a8be",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.14.0",
"versionStartIncluding": "1.0.0-pre.7",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Mat Trudel"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"dateAssigned": "2026-10-23T12:44:41.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eInefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a \u003ccode\u003econtent-length\u003c/code\u003e value or a \u003ccode\u003eHost\u003c/code\u003e or \u003ccode\u003e:authority\u003c/code\u003e port made of thousands of digits.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eBandit.Headers.parse_integer/2\u003c/code\u003e in \u003ccode\u003elib/bandit/headers.ex\u003c/code\u003e builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Inefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a `content-length` value or a `Host` or `:authority` port made of thousands of digits.\n\n`Bandit.Headers.parse_integer/2` in `lib/bandit/headers.ex` builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\n\nThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0."
}
],
"value": "Inefficient Algorithmic Complexity vulnerability in the header integer parser of mtrudel bandit allows an unauthenticated remote attacker to consume server CPU via a content-length value or a Host or :authority port made of thousands of digits.\n\nBandit.Headers.parse_integer/2 in lib/bandit/headers.ex builds the number one digit at a time with no limit on the digit count, allocating a new bignum at each step, so one value costs time quadratic in its length. It runs on raw request input over HTTP/1 and HTTP/2, before any range check. Over HTTP/2, a 4,000-digit value can be stored once in the HPACK dynamic table and re-sent on each new stream for about one byte: 124 KB of traffic kept the server busy for 27.9 s.\n\nThis issue affects bandit: from 1.0.0-pre.7 before 1.14.0."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAn unauthenticated client can make the server spend CPU time out of all proportion to the traffic it sends (27.9 s for 124 KB in the reporter\u0027s test). This affects any Bandit server reachable by untrusted clients over HTTP/1 or HTTP/2, with no special configuration.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "An unauthenticated client can make the server spend CPU time out of all proportion to the traffic it sends (27.9 s for 124 KB in the reporter\u0027s test). This affects any Bandit server reachable by untrusted clients over HTTP/1 or HTTP/2, with no special configuration."
}
],
"value": "An unauthenticated client can make the server spend CPU time out of all proportion to the traffic it sends (27.9 s for 124 KB in the reporter\u0027s test). This affects any Bandit server reachable by untrusted clients over HTTP/1 or HTTP/2, with no special configuration."
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"baseScore": 8.7,
"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:N/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-407",
"description": "CWE-407 Inefficient Algorithmic Complexity",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T13:31:35.033Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "Quadratic bignum parsing of Content-Length and Host port values in Bandit",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-29cr-8477-rg6r"
},
{
"name": "EEF CNA record for CVE-2026-113436",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-113436.html"
},
{
"name": "OSV record EEF-CVE-2026-113436",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-113436"
},
{
"name": "Introducing commit e0c8c0c in mtrudel/bandit",
"tags": [
"related"
],
"url": "https://github.com/mtrudel/bandit/commit/e0c8c0c30af9b0f57d8aafac37ddd9294363a8be"
},
{
"name": "Fix commit 220b9df in mtrudel/bandit",
"tags": [
"patch"
],
"url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
}
],
"source": {
"discovery": "UNKNOWN"
},
"title": "Quadratic bignum parsing of Content-Length and Host port values in Bandit",
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eRun Bandit with any Plug.\u003c/li\u003e\n\u003cli\u003eOpen an HTTP/2 connection with prior knowledge and complete the SETTINGS exchange.\u003c/li\u003e\n\u003cli\u003eIn one write, send 5,000 HEADERS frames for \u003ccode\u003ePOST /\u003c/code\u003e on new streams, each carrying a \u003ccode\u003econtent-length\u003c/code\u003e of 4,000 \u003ccode\u003e9\u003c/code\u003e digits encoded with HPACK indexing, so that every frame after the first refers to the stored value.\u003c/li\u003e\n\u003cli\u003eThe 124,003 bytes take 27.9 s to process before all 5,000 requests reach the Plug.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. Run Bandit with any Plug.\n2. Open an HTTP/2 connection with prior knowledge and complete the SETTINGS exchange.\n3. In one write, send 5,000 HEADERS frames for `POST /` on new streams, each carrying a `content-length` of 4,000 `9` digits encoded with HPACK indexing, so that every frame after the first refers to the stored value.\n4. The 124,003 bytes take 27.9 s to process before all 5,000 requests reach the Plug."
}
],
"value": "* Run Bandit with any Plug.\n* Open an HTTP/2 connection with prior knowledge and complete the SETTINGS exchange.\n* In one write, send 5,000 HEADERS frames for POST / on new streams, each carrying a content-length of 4,000 9 digits encoded with HPACK indexing, so that every frame after the first refers to the stored value.\n* The 124,003 bytes take 27.9 s to process before all 5,000 requests reach the Plug."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Unbounded digit loop.\u003c/strong\u003e \u003ccode\u003eBandit.Headers.parse_integer/2\u003c/code\u003e in \u003ccode\u003elib/bandit/headers.ex\u003c/code\u003e builds the number with \u003ccode\u003etotal * 10 + digit - ?0\u003c/code\u003e and has no limit on the digit count. Each step allocates a new bignum, so parsing one value costs O(n\u00b2). On OTP 28, 10,000 digits take about 10 ms, 50,000 about 250 ms and 80,000 about 560 ms, where \u003ccode\u003eString.to_integer/1\u003c/code\u003e handles the same inputs in 1 to 3 ms.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Reached on raw input.\u003c/strong\u003e It is called from \u003ccode\u003eget_content_length/1\u003c/code\u003e and \u003ccode\u003eparse_hostlike_header!/1\u003c/code\u003e on raw request input, before any range check. An all-digit \u003ccode\u003econtent-length\u003c/code\u003e is returned as \u003ccode\u003e{:ok, huge_int}\u003c/code\u003e, and the \u003ccode\u003eis_port_number\u003c/code\u003e guard only runs after the whole number is built.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. HPACK amplification.\u003c/strong\u003e Over HTTP/2, a 4,000-digit value (about 1.1 ms to parse) can be stored once in the HPACK dynamic table and then re-sent on each new stream for about one byte.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Unbounded digit loop.** `Bandit.Headers.parse_integer/2` in `lib/bandit/headers.ex` builds the number with `total * 10 + digit - ?0` and has no limit on the digit count. Each step allocates a new bignum, so parsing one value costs O(n\u00b2). On OTP 28, 10,000 digits take about 10 ms, 50,000 about 250 ms and 80,000 about 560 ms, where `String.to_integer/1` handles the same inputs in 1 to 3 ms.\n\n**2. Reached on raw input.** It is called from `get_content_length/1` and `parse_hostlike_header!/1` on raw request input, before any range check. An all-digit `content-length` is returned as `{:ok, huge_int}`, and the `is_port_number` guard only runs after the whole number is built.\n\n**3. HPACK amplification.** Over HTTP/2, a 4,000-digit value (about 1.1 ms to parse) can be stored once in the HPACK dynamic table and then re-sent on each new stream for about one byte."
}
],
"value": "1. Unbounded digit loop. Bandit.Headers.parse_integer/2 in lib/bandit/headers.ex builds the number with total * 10 + digit - ?0 and has no limit on the digit count. Each step allocates a new bignum, so parsing one value costs O(n\u00b2). On OTP 28, 10,000 digits take about 10 ms, 50,000 about 250 ms and 80,000 about 560 ms, where String.to_integer/1 handles the same inputs in 1 to 3 ms.\n\n2. Reached on raw input. It is called from get_content_length/1 and parse_hostlike_header!/1 on raw request input, before any range check. An all-digit content-length is returned as {:ok, huge_int}, and the is_port_number guard only runs after the whole number is built.\n\n3. HPACK amplification. Over HTTP/2, a 4,000-digit value (about 1.1 ms to parse) can be stored once in the HPACK dynamic table and then re-sent on each new stream for about one byte."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-113436",
"datePublished": "2026-10-26T13:31:35.033Z",
"dateReserved": "2026-10-23T10:30:01.881Z",
"dateUpdated": "2026-10-26T15:35:51.556Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
}
}
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.
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
How durations are calculated
Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.
Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.
Loading timeline…
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.
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.