CVE-2026-108529 (GCVE-0-2026-108529)
Vulnerability from cvelistv5
Published
2026-10-26 13:35
Modified
2026-10-26 15:35
Severity ?
VLAI Severity ?
EPSS score ?
CWE
- CWE-407 - Inefficient Algorithmic Complexity
Summary
Inefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter's run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.
do_pending_sends/2 in lib/bandit/http2/connection.ex retries every queued send and, before each retry, removes that entry from the queue with List.delete/2, so one frame costs O(n²) list operations for n blocked streams. max_concurrent_streams defaults to :infinity, so the attacker chooses n.
This issue affects bandit: from 0.3.4 before 1.14.0.
References
Impacted products
{
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-108529",
"options": [
{
"Exploitation": "none"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-26T15:01:20.277475Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T15:35:50.781Z",
"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": "0.3.4",
"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": "6feadb31189d18b7dcda6c663112cd3bbaf63a46",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.14.0",
"versionStartIncluding": "0.3.4",
"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-23T10:25:55.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eInefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter\u0027s run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003edo_pending_sends/2\u003c/code\u003e in \u003ccode\u003elib/bandit/http2/connection.ex\u003c/code\u003e retries every queued send and, before each retry, removes that entry from the queue with \u003ccode\u003eList.delete/2\u003c/code\u003e, so one frame costs O(n\u00b2) list operations for n blocked streams. \u003ccode\u003emax_concurrent_streams\u003c/code\u003e defaults to \u003ccode\u003e:infinity\u003c/code\u003e, so the attacker chooses n.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 0.3.4 before 1.14.0.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Inefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter\u0027s run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.\n\n`do_pending_sends/2` in `lib/bandit/http2/connection.ex` retries every queued send and, before each retry, removes that entry from the queue with `List.delete/2`, so one frame costs O(n\u00b2) list operations for n blocked streams. `max_concurrent_streams` defaults to `:infinity`, so the attacker chooses n.\n\nThis issue affects bandit: from 0.3.4 before 1.14.0."
}
],
"value": "Inefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter\u0027s run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.\n\ndo_pending_sends/2 in lib/bandit/http2/connection.ex retries every queued send and, before each retry, removes that entry from the queue with List.delete/2, so one frame costs O(n\u00b2) list operations for n blocked streams. max_concurrent_streams defaults to :infinity, so the attacker chooses n.\n\nThis issue affects bandit: from 0.3.4 before 1.14.0."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAn unauthenticated remote client that keeps thousands of HTTP/2 response streams blocked makes each 9-byte SETTINGS or stream-0 WINDOW_UPDATE frame cost the server quadratic CPU work. A steady trickle of such frames keeps the connection process, and the scheduler running it, busy for as long as the attacker continues.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "An unauthenticated remote client that keeps thousands of HTTP/2 response streams blocked makes each 9-byte SETTINGS or stream-0 WINDOW_UPDATE frame cost the server quadratic CPU work. A steady trickle of such frames keeps the connection process, and the scheduler running it, busy for as long as the attacker continues."
}
],
"value": "An unauthenticated remote client that keeps thousands of HTTP/2 response streams blocked makes each 9-byte SETTINGS or stream-0 WINDOW_UPDATE frame cost the server quadratic CPU work. A steady trickle of such frames keeps the connection process, and the scheduler running it, busy for as long as the attacker continues."
}
]
}
],
"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:35:26.080Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "SETTINGS and stream-0 WINDOW_UPDATE frames trigger quadratic work over blocked streams",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-j363-h72p-296m"
},
{
"name": "EEF CNA record for CVE-2026-108529",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-108529.html"
},
{
"name": "OSV record EEF-CVE-2026-108529",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-108529"
},
{
"name": "Introducing commit 6feadb3 in mtrudel/bandit",
"tags": [
"related"
],
"url": "https://github.com/mtrudel/bandit/commit/6feadb31189d18b7dcda6c663112cd3bbaf63a46"
},
{
"name": "Fix commit 220b9df in mtrudel/bandit",
"tags": [
"patch"
],
"url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
}
],
"source": {
"discovery": "UNKNOWN"
},
"title": "SETTINGS and stream-0 WINDOW_UPDATE frames trigger quadratic work over blocked streams in Bandit",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eFrom 1.9.0, bound the number of streams a client can open, for example with \u003ccode\u003ehttp_2_options: [default_local_settings: [max_concurrent_streams: 100]]\u003c/code\u003e, which bounds the work each frame can cause. From 0.7.0, disabling HTTP/2 with \u003ccode\u003ehttp_2_options: [enabled: false]\u003c/code\u003e removes the vulnerable path.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "From 1.9.0, bound the number of streams a client can open, for example with `http_2_options: [default_local_settings: [max_concurrent_streams: 100]]`, which bounds the work each frame can cause. From 0.7.0, disabling HTTP/2 with `http_2_options: [enabled: false]` removes the vulnerable path."
}
],
"value": "From 1.9.0, bound the number of streams a client can open, for example with http_2_options: [default_local_settings: [max_concurrent_streams: 100]], which bounds the work each frame can cause. From 0.7.0, disabling HTTP/2 with http_2_options: [enabled: false] removes the vulnerable path."
}
],
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eOn one HTTP/2 connection, send 3,000 requests to an endpoint with a 20 KB response body, and send no connection-level \u003ccode\u003eWINDOW_UPDATE\u003c/code\u003e, so the responses queue in \u003ccode\u003epending_sends\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSend an empty SETTINGS frame followed by a PING.\u003c/li\u003e\n\u003cli\u003eTime the PING acknowledgement. In the reporter\u0027s run, the single 9-byte SETTINGS frame delayed it by 133 ms. Repeating the frame keeps the connection process busy.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. On one HTTP/2 connection, send 3,000 requests to an endpoint with a 20 KB response body, and send no connection-level `WINDOW_UPDATE`, so the responses queue in `pending_sends`.\n2. Send an empty SETTINGS frame followed by a PING.\n3. Time the PING acknowledgement. In the reporter\u0027s run, the single 9-byte SETTINGS frame delayed it by 133 ms. Repeating the frame keeps the connection process busy."
}
],
"value": "* On one HTTP/2 connection, send 3,000 requests to an endpoint with a 20 KB response body, and send no connection-level WINDOW_UPDATE, so the responses queue in pending_sends.\n* Send an empty SETTINGS frame followed by a PING.\n* Time the PING acknowledgement. In the reporter\u0027s run, the single 9-byte SETTINGS frame delayed it by 133 ms. Repeating the frame keeps the connection process busy."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Blocked sends\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eA response that outruns the connection send window is queued in \u003ccode\u003epending_sends\u003c/code\u003e. With \u003ccode\u003emax_concurrent_streams\u003c/code\u003e defaulting to \u003ccode\u003e:infinity\u003c/code\u003e and no connection-level \u003ccode\u003eWINDOW_UPDATE\u003c/code\u003e from the client, every one of n streams ends up queued.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Trigger\u003c/strong\u003e (\u003ccode\u003elib/bandit/http2/connection.ex\u003c/code\u003e)\u003c/p\u003e\n\u003cp\u003eEvery non-ACK SETTINGS frame and every \u003ccode\u003eWINDOW_UPDATE\u003c/code\u003e on stream 0 calls \u003ccode\u003edo_pending_sends/2\u003c/code\u003e. SETTINGS handling also sends \u003ccode\u003edeliver_send_window_update\u003c/code\u003e to every stream even when the window delta is 0, so unread messages pile up in the mailboxes of blocked streams.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Quadratic drain\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003edo_pending_sends/2\u003c/code\u003e walks the queue and calls \u003ccode\u003eList.delete/2\u003c/code\u003e on the whole list before retrying each entry, putting it back at the front if the send is still blocked. One frame therefore costs O(n\u00b2) list operations, about 10^8 at n = 10,000.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Blocked sends**\n\nA response that outruns the connection send window is queued in `pending_sends`. With `max_concurrent_streams` defaulting to `:infinity` and no connection-level `WINDOW_UPDATE` from the client, every one of n streams ends up queued.\n\n**2. Trigger** (`lib/bandit/http2/connection.ex`)\n\nEvery non-ACK SETTINGS frame and every `WINDOW_UPDATE` on stream 0 calls `do_pending_sends/2`. SETTINGS handling also sends `deliver_send_window_update` to every stream even when the window delta is 0, so unread messages pile up in the mailboxes of blocked streams.\n\n**3. Quadratic drain**\n\n`do_pending_sends/2` walks the queue and calls `List.delete/2` on the whole list before retrying each entry, putting it back at the front if the send is still blocked. One frame therefore costs O(n\u00b2) list operations, about 10^8 at n = 10,000."
}
],
"value": "1. Blocked sends\n\nA response that outruns the connection send window is queued in pending_sends. With max_concurrent_streams defaulting to :infinity and no connection-level WINDOW_UPDATE from the client, every one of n streams ends up queued.\n\n2. Trigger (lib/bandit/http2/connection.ex)\n\nEvery non-ACK SETTINGS frame and every WINDOW_UPDATE on stream 0 calls do_pending_sends/2. SETTINGS handling also sends deliver_send_window_update to every stream even when the window delta is 0, so unread messages pile up in the mailboxes of blocked streams.\n\n3. Quadratic drain\n\ndo_pending_sends/2 walks the queue and calls List.delete/2 on the whole list before retrying each entry, putting it back at the front if the send is still blocked. One frame therefore costs O(n\u00b2) list operations, about 10^8 at n = 10,000."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-108529",
"datePublished": "2026-10-26T13:35:26.080Z",
"dateReserved": "2026-10-12T16:15:01.628Z",
"dateUpdated": "2026-10-26T15:35:50.781Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"vulnrichment": {
"containers": "{\"adp\": [{\"title\": \"CISA ADP Vulnrichment\", \"metrics\": [{\"other\": {\"type\": \"ssvc\", \"content\": {\"id\": \"CVE-2026-108529\", \"role\": \"CISA Coordinator\", \"options\": [{\"Exploitation\": \"none\"}, {\"Automatable\": \"yes\"}, {\"Technical Impact\": \"partial\"}], \"version\": \"2.0.3\", \"timestamp\": \"2026-10-26T15:01:20.277475Z\"}}}], \"providerMetadata\": {\"orgId\": \"134c704f-9b21-4f2e-91b3-4a467353bcc0\", \"shortName\": \"CISA-ADP\", \"dateUpdated\": \"2026-10-26T15:32:23.882Z\"}}], \"cna\": {\"title\": \"SETTINGS and stream-0 WINDOW_UPDATE frames trigger quadratic work over blocked streams in Bandit\", \"source\": {\"discovery\": \"UNKNOWN\"}, \"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\"}], \"impacts\": [{\"capecId\": \"CAPEC-130\", \"descriptions\": [{\"lang\": \"en\", \"value\": \"An unauthenticated remote client that keeps thousands of HTTP/2 response streams blocked makes each 9-byte SETTINGS or stream-0 WINDOW_UPDATE frame cost the server quadratic CPU work. A steady trickle of such frames keeps the connection process, and the scheduler running it, busy for as long as the attacker continues.\", \"supportingMedia\": [{\"type\": \"text/html\", \"value\": \"\u003cp\u003eAn unauthenticated remote client that keeps thousands of HTTP/2 response streams blocked makes each 9-byte SETTINGS or stream-0 WINDOW_UPDATE frame cost the server quadratic CPU work. A steady trickle of such frames keeps the connection process, and the scheduler running it, busy for as long as the attacker continues.\u003c/p\u003e\", \"base64\": false}, {\"type\": \"text/markdown\", \"value\": \"An unauthenticated remote client that keeps thousands of HTTP/2 response streams blocked makes each 9-byte SETTINGS or stream-0 WINDOW_UPDATE frame cost the server quadratic CPU work. A steady trickle of such frames keeps the connection process, and the scheduler running it, busy for as long as the attacker continues.\", \"base64\": false}]}]}], \"metrics\": [{\"format\": \"CVSS\", \"cvssV4_0\": {\"Safety\": \"NOT_DEFINED\", \"version\": \"4.0\", \"Recovery\": \"NOT_DEFINED\", \"baseScore\": 8.7, \"Automatable\": \"NOT_DEFINED\", \"attackVector\": \"NETWORK\", \"baseSeverity\": \"HIGH\", \"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\", \"providerUrgency\": \"NOT_DEFINED\", \"userInteraction\": \"NONE\", \"attackComplexity\": \"LOW\", \"attackRequirements\": \"NONE\", \"privilegesRequired\": \"NONE\", \"subIntegrityImpact\": \"NONE\", \"vulnIntegrityImpact\": \"NONE\", \"subAvailabilityImpact\": \"NONE\", \"vulnAvailabilityImpact\": \"HIGH\", \"subConfidentialityImpact\": \"NONE\", \"vulnConfidentialityImpact\": \"NONE\", \"vulnerabilityResponseEffort\": \"NOT_DEFINED\"}, \"scenarios\": [{\"lang\": \"en\", \"value\": \"GENERAL\"}]}], \"affected\": [{\"cpes\": [\"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*\"], \"repo\": \"https://github.com/mtrudel/bandit\", \"vendor\": \"mtrudel\", \"product\": \"bandit\", \"versions\": [{\"status\": \"affected\", \"version\": \"0.3.4\", \"lessThan\": \"1.14.0\", \"versionType\": \"semver\"}], \"packageURL\": \"pkg:hex/bandit\", \"packageName\": \"bandit\", \"collectionURL\": \"https://repo.hex.pm\", \"defaultStatus\": \"unaffected\"}, {\"cpes\": [\"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*\"], \"repo\": \"https://github.com/mtrudel/bandit\", \"vendor\": \"mtrudel\", \"product\": \"bandit\", \"versions\": [{\"status\": \"affected\", \"version\": \"6feadb31189d18b7dcda6c663112cd3bbaf63a46\", \"lessThan\": \"220b9dfd27f9a21305be2afc75cbe585ddc24e7a\", \"versionType\": \"git\"}], \"packageURL\": \"pkg:github/mtrudel/bandit\", \"packageName\": \"mtrudel/bandit\", \"collectionURL\": \"https://github.com\", \"defaultStatus\": \"unaffected\"}], \"references\": [{\"url\": \"https://github.com/mtrudel/bandit/security/advisories/GHSA-j363-h72p-296m\", \"name\": \"SETTINGS and stream-0 WINDOW_UPDATE frames trigger quadratic work over blocked streams\", \"tags\": [\"vendor-advisory\", \"related\"]}, {\"url\": \"https://cna.erlef.org/cves/CVE-2026-108529.html\", \"name\": \"EEF CNA record for CVE-2026-108529\", \"tags\": [\"related\"]}, {\"url\": \"https://osv.dev/vulnerability/EEF-CVE-2026-108529\", \"name\": \"OSV record EEF-CVE-2026-108529\", \"tags\": [\"related\"]}, {\"url\": \"https://github.com/mtrudel/bandit/commit/6feadb31189d18b7dcda6c663112cd3bbaf63a46\", \"name\": \"Introducing commit 6feadb3 in mtrudel/bandit\", \"tags\": [\"related\"]}, {\"url\": \"https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a\", \"name\": \"Fix commit 220b9df in mtrudel/bandit\", \"tags\": [\"patch\"]}], \"workarounds\": [{\"lang\": \"en\", \"value\": \"From 1.9.0, bound the number of streams a client can open, for example with http_2_options: [default_local_settings: [max_concurrent_streams: 100]], which bounds the work each frame can cause. From 0.7.0, disabling HTTP/2 with http_2_options: [enabled: false] removes the vulnerable path.\", \"supportingMedia\": [{\"type\": \"text/html\", \"value\": \"\u003cp\u003eFrom 1.9.0, bound the number of streams a client can open, for example with \u003ccode\u003ehttp_2_options: [default_local_settings: [max_concurrent_streams: 100]]\u003c/code\u003e, which bounds the work each frame can cause. From 0.7.0, disabling HTTP/2 with \u003ccode\u003ehttp_2_options: [enabled: false]\u003c/code\u003e removes the vulnerable path.\u003c/p\u003e\", \"base64\": false}, {\"type\": \"text/markdown\", \"value\": \"From 1.9.0, bound the number of streams a client can open, for example with `http_2_options: [default_local_settings: [max_concurrent_streams: 100]]`, which bounds the work each frame can cause. From 0.7.0, disabling HTTP/2 with `http_2_options: [enabled: false]` removes the vulnerable path.\", \"base64\": false}]}], \"dateAssigned\": \"2026-10-23T10:25:55.000Z\", \"descriptions\": [{\"lang\": \"en\", \"value\": \"Inefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter\u0027s run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.\\n\\ndo_pending_sends/2 in lib/bandit/http2/connection.ex retries every queued send and, before each retry, removes that entry from the queue with List.delete/2, so one frame costs O(n\\u00b2) list operations for n blocked streams. max_concurrent_streams defaults to :infinity, so the attacker chooses n.\\n\\nThis issue affects bandit: from 0.3.4 before 1.14.0.\", \"supportingMedia\": [{\"type\": \"text/html\", \"value\": \"\u003cp\u003eInefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter\u0027s run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.\u003c/p\u003e\\n\u003cp\u003e\u003ccode\u003edo_pending_sends/2\u003c/code\u003e in \u003ccode\u003elib/bandit/http2/connection.ex\u003c/code\u003e retries every queued send and, before each retry, removes that entry from the queue with \u003ccode\u003eList.delete/2\u003c/code\u003e, so one frame costs O(n\\u00b2) list operations for n blocked streams. \u003ccode\u003emax_concurrent_streams\u003c/code\u003e defaults to \u003ccode\u003e:infinity\u003c/code\u003e, so the attacker chooses n.\u003c/p\u003e\\n\u003cp\u003eThis issue affects bandit: from 0.3.4 before 1.14.0.\u003c/p\u003e\", \"base64\": false}, {\"type\": \"text/markdown\", \"value\": \"Inefficient Algorithmic Complexity vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server CPU via small SETTINGS or connection-level WINDOW_UPDATE frames. The attacker opens thousands of streams whose responses block on the connection send window, then sends cheap frames that each make the server walk the whole queue of blocked sends. In the reporter\u0027s run, with 3,000 blocked streams a single 9-byte SETTINGS frame took 133 ms to process.\\n\\n`do_pending_sends/2` in `lib/bandit/http2/connection.ex` retries every queued send and, before each retry, removes that entry from the queue with `List.delete/2`, so one frame costs O(n\\u00b2) list operations for n blocked streams. `max_concurrent_streams` defaults to `:infinity`, so the attacker chooses n.\\n\\nThis issue affects bandit: from 0.3.4 before 1.14.0.\", \"base64\": false}]}], \"problemTypes\": [{\"descriptions\": [{\"lang\": \"en\", \"type\": \"CWE\", \"cweId\": \"CWE-407\", \"description\": \"CWE-407 Inefficient Algorithmic Complexity\"}]}], \"cpeApplicability\": [{\"nodes\": [{\"negate\": false, \"cpeMatch\": [{\"criteria\": \"cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*\", \"vulnerable\": true, \"versionEndExcluding\": \"1.14.0\", \"versionStartIncluding\": \"0.3.4\"}], \"operator\": \"OR\"}], \"operator\": \"AND\"}], \"providerMetadata\": {\"orgId\": \"6b3ad84c-e1a6-4bf7-a703-f496b71e49db\", \"shortName\": \"EEF\", \"dateUpdated\": \"2026-10-26T13:35:26.080Z\"}, \"x_proofOfConcept\": [{\"lang\": \"en\", \"value\": \"* On one HTTP/2 connection, send 3,000 requests to an endpoint with a 20 KB response body, and send no connection-level WINDOW_UPDATE, so the responses queue in pending_sends.\\n* Send an empty SETTINGS frame followed by a PING.\\n* Time the PING acknowledgement. In the reporter\u0027s run, the single 9-byte SETTINGS frame delayed it by 133 ms. Repeating the frame keeps the connection process busy.\", \"supportingMedia\": [{\"type\": \"text/html\", \"value\": \"\u003col\u003e\\n\u003cli\u003eOn one HTTP/2 connection, send 3,000 requests to an endpoint with a 20 KB response body, and send no connection-level \u003ccode\u003eWINDOW_UPDATE\u003c/code\u003e, so the responses queue in \u003ccode\u003epending_sends\u003c/code\u003e.\u003c/li\u003e\\n\u003cli\u003eSend an empty SETTINGS frame followed by a PING.\u003c/li\u003e\\n\u003cli\u003eTime the PING acknowledgement. In the reporter\u0027s run, the single 9-byte SETTINGS frame delayed it by 133 ms. Repeating the frame keeps the connection process busy.\u003c/li\u003e\\n\u003c/ol\u003e\", \"base64\": false}, {\"type\": \"text/markdown\", \"value\": \"1. On one HTTP/2 connection, send 3,000 requests to an endpoint with a 20 KB response body, and send no connection-level `WINDOW_UPDATE`, so the responses queue in `pending_sends`.\\n2. Send an empty SETTINGS frame followed by a PING.\\n3. Time the PING acknowledgement. In the reporter\u0027s run, the single 9-byte SETTINGS frame delayed it by 133 ms. Repeating the frame keeps the connection process busy.\", \"base64\": false}]}], \"x_technicalAnalysis\": [{\"lang\": \"en\", \"value\": \"1. Blocked sends\\n\\nA response that outruns the connection send window is queued in pending_sends. With max_concurrent_streams defaulting to :infinity and no connection-level WINDOW_UPDATE from the client, every one of n streams ends up queued.\\n\\n2. Trigger (lib/bandit/http2/connection.ex)\\n\\nEvery non-ACK SETTINGS frame and every WINDOW_UPDATE on stream 0 calls do_pending_sends/2. SETTINGS handling also sends deliver_send_window_update to every stream even when the window delta is 0, so unread messages pile up in the mailboxes of blocked streams.\\n\\n3. Quadratic drain\\n\\ndo_pending_sends/2 walks the queue and calls List.delete/2 on the whole list before retrying each entry, putting it back at the front if the send is still blocked. One frame therefore costs O(n\\u00b2) list operations, about 10^8 at n = 10,000.\", \"supportingMedia\": [{\"type\": \"text/html\", \"value\": \"\u003cp\u003e\u003cstrong\u003e1. Blocked sends\u003c/strong\u003e\u003c/p\u003e\\n\u003cp\u003eA response that outruns the connection send window is queued in \u003ccode\u003epending_sends\u003c/code\u003e. With \u003ccode\u003emax_concurrent_streams\u003c/code\u003e defaulting to \u003ccode\u003e:infinity\u003c/code\u003e and no connection-level \u003ccode\u003eWINDOW_UPDATE\u003c/code\u003e from the client, every one of n streams ends up queued.\u003c/p\u003e\\n\u003cp\u003e\u003cstrong\u003e2. Trigger\u003c/strong\u003e (\u003ccode\u003elib/bandit/http2/connection.ex\u003c/code\u003e)\u003c/p\u003e\\n\u003cp\u003eEvery non-ACK SETTINGS frame and every \u003ccode\u003eWINDOW_UPDATE\u003c/code\u003e on stream 0 calls \u003ccode\u003edo_pending_sends/2\u003c/code\u003e. SETTINGS handling also sends \u003ccode\u003edeliver_send_window_update\u003c/code\u003e to every stream even when the window delta is 0, so unread messages pile up in the mailboxes of blocked streams.\u003c/p\u003e\\n\u003cp\u003e\u003cstrong\u003e3. Quadratic drain\u003c/strong\u003e\u003c/p\u003e\\n\u003cp\u003e\u003ccode\u003edo_pending_sends/2\u003c/code\u003e walks the queue and calls \u003ccode\u003eList.delete/2\u003c/code\u003e on the whole list before retrying each entry, putting it back at the front if the send is still blocked. One frame therefore costs O(n\\u00b2) list operations, about 10^8 at n = 10,000.\u003c/p\u003e\", \"base64\": false}, {\"type\": \"text/markdown\", \"value\": \"**1. Blocked sends**\\n\\nA response that outruns the connection send window is queued in `pending_sends`. With `max_concurrent_streams` defaulting to `:infinity` and no connection-level `WINDOW_UPDATE` from the client, every one of n streams ends up queued.\\n\\n**2. Trigger** (`lib/bandit/http2/connection.ex`)\\n\\nEvery non-ACK SETTINGS frame and every `WINDOW_UPDATE` on stream 0 calls `do_pending_sends/2`. SETTINGS handling also sends `deliver_send_window_update` to every stream even when the window delta is 0, so unread messages pile up in the mailboxes of blocked streams.\\n\\n**3. Quadratic drain**\\n\\n`do_pending_sends/2` walks the queue and calls `List.delete/2` on the whole list before retrying each entry, putting it back at the front if the send is still blocked. One frame therefore costs O(n\\u00b2) list operations, about 10^8 at n = 10,000.\", \"base64\": false}]}]}}",
"cveMetadata": "{\"cveId\": \"CVE-2026-108529\", \"state\": \"PUBLISHED\", \"dateUpdated\": \"2026-10-26T15:35:50.781Z\", \"dateReserved\": \"2026-10-12T16:15:01.628Z\", \"assignerOrgId\": \"6b3ad84c-e1a6-4bf7-a703-f496b71e49db\", \"datePublished\": \"2026-10-26T13:35:26.080Z\", \"assignerShortName\": \"EEF\"}",
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
}
}
Loading…
Loading…
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.
Loading…
Loading…