CVE-2026-115269 (GCVE-0-2026-115269)

Vulnerability from cvelistv5 – Published: 2026-10-26 13:30 – Updated: 2026-10-26 15:35
VLAI
Title
HTTP/2 WINDOW_UPDATE and SETTINGS frames reset the request body read timeout in Bandit
Summary
Allocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body. Bandit.HTTP2.Stream.do_read_data/4 in lib/bandit/http2/stream.ex waits for each frame with a fresh read_timeout. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps read_body blocked, together with the stream process and whatever the application holds while reading, for as long as it likes. This issue affects bandit: from 1.4.0 before 1.14.0.
SSVC
Exploitation: none Automatable: yes Technical Impact: partial
CISA Coordinator · CISA-ADP (v2.0.3)
Decision recorded 2026-10-26 15:02 UTC
CWE
  • CWE-835 - Loop with Unreachable Exit Condition ('Infinite Loop')
  • CWE-770 - Allocation of Resources Without Limits or Throttling
Assigner
EEF CNA under the mitre root
CNA scorecard A 97/100 over 341 records in the last 180 days details
Impacted products
Vendor Product Version CPE status
mtrudel bandit Affected: 1.4.0 , < 1.14.0 (semver)
    cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*
Create a notification for this product.
mtrudel bandit Affected: fff06efe3be962b484bd4d3eb339372fda5a231f , < 220b9dfd27f9a21305be2afc75cbe585ddc24e7a (git)
    cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*
Create a notification for this product.
Show details on NVD website

{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2026-115269",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "yes"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-26T15:02:19.174445Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-10-26T15:35:52.079Z",
          "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.4.0",
              "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": "fff06efe3be962b484bd4d3eb339372fda5a231f",
              "versionType": "git"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "1.14.0",
                  "versionStartIncluding": "1.4.0",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ],
          "operator": "AND"
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "analyst",
          "value": "Peter Ullrich"
        },
        {
          "lang": "en",
          "type": "reporter",
          "value": "Daniel Coles"
        },
        {
          "lang": "en",
          "type": "remediation developer",
          "value": "Mat Trudel"
        },
        {
          "lang": "en",
          "type": "analyst",
          "value": "Jonatan M\u00e4nnchen / EEF"
        }
      ],
      "dateAssigned": "2026-10-23T13:25:29.000Z",
      "descriptions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eAllocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eBandit.HTTP2.Stream.do_read_data/4\u003c/code\u003e in \u003ccode\u003elib/bandit/http2/stream.ex\u003c/code\u003e waits for each frame with a fresh \u003ccode\u003eread_timeout\u003c/code\u003e. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps \u003ccode\u003eread_body\u003c/code\u003e blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 1.4.0 before 1.14.0.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Allocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\n\n`Bandit.HTTP2.Stream.do_read_data/4` in `lib/bandit/http2/stream.ex` waits for each frame with a fresh `read_timeout`. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps `read_body` blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\n\nThis issue affects bandit: from 1.4.0 before 1.14.0."
            }
          ],
          "value": "Allocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\n\nBandit.HTTP2.Stream.do_read_data/4 in lib/bandit/http2/stream.ex waits for each frame with a fresh read_timeout. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps read_body blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\n\nThis issue affects bandit: from 1.4.0 before 1.14.0."
        }
      ],
      "impacts": [
        {
          "capecId": "CAPEC-469",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eAn unauthenticated client can keep a Bandit HTTP/2 stream, and whatever its request handler holds while reading the body, occupied indefinitely for 9 bytes per \u003ccode\u003eread_timeout\u003c/code\u003e, and repeat this across many streams and connections. This affects any Bandit server with HTTP/2 enabled whose routes read request bodies, which \u003ccode\u003ePlug.Parsers\u003c/code\u003e does for POST, PUT and PATCH.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "An unauthenticated client can keep a Bandit HTTP/2 stream, and whatever its request handler holds while reading the body, occupied indefinitely for 9 bytes per `read_timeout`, and repeat this across many streams and connections. This affects any Bandit server with HTTP/2 enabled whose routes read request bodies, which `Plug.Parsers` does for POST, PUT and PATCH."
                }
              ],
              "value": "An unauthenticated client can keep a Bandit HTTP/2 stream, and whatever its request handler holds while reading the body, occupied indefinitely for 9 bytes per read_timeout, and repeat this across many streams and connections. This affects any Bandit server with HTTP/2 enabled whose routes read request bodies, which Plug.Parsers does for POST, PUT and PATCH."
            }
          ]
        }
      ],
      "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-835",
              "description": "CWE-835 Loop with Unreachable Exit Condition (\u0027Infinite Loop\u0027)",
              "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:30:24.621Z",
        "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "shortName": "EEF"
      },
      "references": [
        {
          "name": "HTTP/2 WINDOW_UPDATE and SETTINGS frames reset the request body read timeout in Bandit",
          "tags": [
            "vendor-advisory",
            "related"
          ],
          "url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-p2qv-vx88-385x"
        },
        {
          "name": "EEF CNA record for CVE-2026-115269",
          "tags": [
            "related"
          ],
          "url": "https://cna.erlef.org/cves/CVE-2026-115269.html"
        },
        {
          "name": "OSV record EEF-CVE-2026-115269",
          "tags": [
            "related"
          ],
          "url": "https://osv.dev/vulnerability/EEF-CVE-2026-115269"
        },
        {
          "name": "Introducing commit fff06ef in mtrudel/bandit",
          "tags": [
            "related"
          ],
          "url": "https://github.com/mtrudel/bandit/commit/fff06efe3be962b484bd4d3eb339372fda5a231f"
        },
        {
          "name": "Fix commit 220b9df in mtrudel/bandit",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
        }
      ],
      "source": {
        "discovery": "UNKNOWN"
      },
      "title": "HTTP/2 WINDOW_UPDATE and SETTINGS frames reset the request body read timeout in Bandit",
      "workarounds": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eDisable HTTP/2 with \u003ccode\u003ehttp_2_options: [enabled: false]\u003c/code\u003e, so that the vulnerable read path never runs.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Disable HTTP/2 with `http_2_options: [enabled: false]`, so that the vulnerable read path never runs."
            }
          ],
          "value": "Disable HTTP/2 with http_2_options: [enabled: false], so that the vulnerable read path never runs."
        }
      ],
      "x_proofOfConcept": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003col\u003e\n\u003cli\u003eRun Bandit with a Plug that calls \u003ccode\u003ePlug.Conn.read_body/2\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eOpen an HTTP/2 connection and send HEADERS for \u003ccode\u003ePOST /\u003c/code\u003e on stream 1 without END_STREAM.\u003c/li\u003e\n\u003cli\u003eEvery 10 seconds, send a WINDOW_UPDATE on stream 1 with an increment of 1.\u003c/li\u003e\n\u003cli\u003eThe stream stays open for 120 s, eight times the default 15 s \u003ccode\u003eread_timeout\u003c/code\u003e. Without the WINDOW_UPDATE frames, the server ends the read after about 15 s.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. Run Bandit with a Plug that calls `Plug.Conn.read_body/2`.\n2. Open an HTTP/2 connection and send HEADERS for `POST /` on stream 1 without END_STREAM.\n3. Every 10 seconds, send a WINDOW_UPDATE on stream 1 with an increment of 1.\n4. The stream stays open for 120 s, eight times the default 15 s `read_timeout`. Without the WINDOW_UPDATE frames, the server ends the read after about 15 s."
            }
          ],
          "value": "* Run Bandit with a Plug that calls Plug.Conn.read_body/2.\n* Open an HTTP/2 connection and send HEADERS for POST / on stream 1 without END_STREAM.\n* Every 10 seconds, send a WINDOW_UPDATE on stream 1 with an increment of 1.\n* The stream stays open for 120 s, eight times the default 15 s read_timeout. Without the WINDOW_UPDATE frames, the server ends the read after about 15 s."
        }
      ],
      "x_technicalAnalysis": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003e\u003cstrong\u003e1. Per-receive timeout.\u003c/strong\u003e \u003ccode\u003eBandit.HTTP2.Stream.read_data/2\u003c/code\u003e passes a flat \u003ccode\u003eread_timeout\u003c/code\u003e (default 15,000 ms) to \u003ccode\u003edo_read_data/4\u003c/code\u003e, which blocks in \u003ccode\u003edo_recv/2\u003c/code\u003e\u0027s \u003ccode\u003ereceive ... after timeout\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Non-progress frames end the wait.\u003c/strong\u003e A stream WINDOW_UPDATE, delivered through \u003ccode\u003eBandit.HTTP2.Connection.handle_frame/3\u003c/code\u003e, or an empty SETTINGS frame, which delivers a zero-delta window update to every stream, is matched inside that \u003ccode\u003ereceive\u003c/code\u003e. \u003ccode\u003edo_recv_send_window_update/2\u003c/code\u003e returns a bare \u003ccode\u003e%Stream{}\u003c/code\u003e, and \u003ccode\u003edo_read_data/4\u003c/code\u003e recurses with the identical \u003ccode\u003etimeout\u003c/code\u003e, restarting the countdown.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Nothing else bounds the read.\u003c/strong\u003e The transport read timeout fires only when no bytes arrive, \u003ccode\u003emax_bytes\u003c/code\u003e is decremented only by DATA frames, and neither WINDOW_UPDATE nor SETTINGS frames are rate limited. The send path in \u003ccode\u003edo_send_data/4\u003c/code\u003e uses a progress-based deadline; the read path does not.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "**1. Per-receive timeout.** `Bandit.HTTP2.Stream.read_data/2` passes a flat `read_timeout` (default 15,000 ms) to `do_read_data/4`, which blocks in `do_recv/2`\u0027s `receive ... after timeout`.\n\n**2. Non-progress frames end the wait.** A stream WINDOW_UPDATE, delivered through `Bandit.HTTP2.Connection.handle_frame/3`, or an empty SETTINGS frame, which delivers a zero-delta window update to every stream, is matched inside that `receive`. `do_recv_send_window_update/2` returns a bare `%Stream{}`, and `do_read_data/4` recurses with the identical `timeout`, restarting the countdown.\n\n**3. Nothing else bounds the read.** The transport read timeout fires only when no bytes arrive, `max_bytes` is decremented only by DATA frames, and neither WINDOW_UPDATE nor SETTINGS frames are rate limited. The send path in `do_send_data/4` uses a progress-based deadline; the read path does not."
            }
          ],
          "value": "1. Per-receive timeout. Bandit.HTTP2.Stream.read_data/2 passes a flat read_timeout (default 15,000 ms) to do_read_data/4, which blocks in do_recv/2\u0027s receive ... after timeout.\n\n2. Non-progress frames end the wait. A stream WINDOW_UPDATE, delivered through Bandit.HTTP2.Connection.handle_frame/3, or an empty SETTINGS frame, which delivers a zero-delta window update to every stream, is matched inside that receive. do_recv_send_window_update/2 returns a bare %Stream{}, and do_read_data/4 recurses with the identical timeout, restarting the countdown.\n\n3. Nothing else bounds the read. The transport read timeout fires only when no bytes arrive, max_bytes is decremented only by DATA frames, and neither WINDOW_UPDATE nor SETTINGS frames are rate limited. The send path in do_send_data/4 uses a progress-based deadline; the read path does not."
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
    "assignerShortName": "EEF",
    "cveId": "CVE-2026-115269",
    "datePublished": "2026-10-26T13:30:24.621Z",
    "dateReserved": "2026-10-23T10:15:01.872Z",
    "dateUpdated": "2026-10-26T15:35:52.079Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "epss": {
      "cve": "CVE-2026-115269",
      "date": "2026-10-28",
      "epss": "0.00602",
      "percentile": "0.48677"
    },
    "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.4.0",
                    "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": "fff06efe3be962b484bd4d3eb339372fda5a231f",
                    "versionType": "git"
                  }
                ]
              }
            ],
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db"
          }
        ],
        "cveTags": [],
        "descriptions": [
          {
            "lang": "en",
            "value": "Allocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\n\nBandit.HTTP2.Stream.do_read_data/4 in lib/bandit/http2/stream.ex waits for each frame with a fresh read_timeout. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps read_body blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\n\nThis issue affects bandit: from 1.4.0 before 1.14.0."
          }
        ],
        "id": "CVE-2026-115269",
        "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-115269",
                "options": [
                  {
                    "exploitation": "none"
                  },
                  {
                    "automatable": "yes"
                  },
                  {
                    "technicalImpact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-26T15:02:19.174445Z",
                "version": "2.0.3"
              }
            }
          ]
        },
        "published": "2026-10-26T14:16:31.290",
        "references": [
          {
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "url": "https://cna.erlef.org/cves/CVE-2026-115269.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/fff06efe3be962b484bd4d3eb339372fda5a231f"
          },
          {
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-p2qv-vx88-385x"
          },
          {
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "url": "https://osv.dev/vulnerability/EEF-CVE-2026-115269"
          }
        ],
        "sourceIdentifier": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "vulnStatus": "Awaiting Analysis",
        "weaknesses": [
          {
            "description": [
              {
                "lang": "en",
                "value": "CWE-770"
              },
              {
                "lang": "en",
                "value": "CWE-835"
              }
            ],
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "type": "Secondary"
          }
        ]
      }
    },
    "vulnrichment": {
      "containers": {
        "adp": [
          {
            "metrics": [
              {
                "other": {
                  "content": {
                    "id": "CVE-2026-115269",
                    "options": [
                      {
                        "Exploitation": "none"
                      },
                      {
                        "Automatable": "yes"
                      },
                      {
                        "Technical Impact": "partial"
                      }
                    ],
                    "role": "CISA Coordinator",
                    "timestamp": "2026-10-26T15:02:19.174445Z",
                    "version": "2.0.3"
                  },
                  "type": "ssvc"
                }
              }
            ],
            "providerMetadata": {
              "dateUpdated": "2026-10-26T15:33:07.848Z",
              "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.4.0",
                  "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": "fff06efe3be962b484bd4d3eb339372fda5a231f",
                  "versionType": "git"
                }
              ]
            }
          ],
          "cpeApplicability": [
            {
              "nodes": [
                {
                  "cpeMatch": [
                    {
                      "criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
                      "versionEndExcluding": "1.14.0",
                      "versionStartIncluding": "1.4.0",
                      "vulnerable": true
                    }
                  ],
                  "negate": false,
                  "operator": "OR"
                }
              ],
              "operator": "AND"
            }
          ],
          "credits": [
            {
              "lang": "en",
              "type": "analyst",
              "value": "Peter Ullrich"
            },
            {
              "lang": "en",
              "type": "reporter",
              "value": "Daniel Coles"
            },
            {
              "lang": "en",
              "type": "remediation developer",
              "value": "Mat Trudel"
            },
            {
              "lang": "en",
              "type": "analyst",
              "value": "Jonatan M\u00e4nnchen / EEF"
            }
          ],
          "dateAssigned": "2026-10-23T13:25:29.000Z",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eAllocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eBandit.HTTP2.Stream.do_read_data/4\u003c/code\u003e in \u003ccode\u003elib/bandit/http2/stream.ex\u003c/code\u003e waits for each frame with a fresh \u003ccode\u003eread_timeout\u003c/code\u003e. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps \u003ccode\u003eread_body\u003c/code\u003e blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 1.4.0 before 1.14.0.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "Allocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\n\n`Bandit.HTTP2.Stream.do_read_data/4` in `lib/bandit/http2/stream.ex` waits for each frame with a fresh `read_timeout`. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps `read_body` blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\n\nThis issue affects bandit: from 1.4.0 before 1.14.0."
                }
              ],
              "value": "Allocation of Resources Without Limits or Throttling vulnerability in the HTTP/2 request body reader of mtrudel bandit allows an unauthenticated remote attacker to hold stream processes open indefinitely via WINDOW_UPDATE or empty SETTINGS frames sent while a Plug reads the request body.\n\nBandit.HTTP2.Stream.do_read_data/4 in lib/bandit/http2/stream.ex waits for each frame with a fresh read_timeout. A stream WINDOW_UPDATE, or the zero-delta window update that every empty SETTINGS frame delivers to all streams, ends the wait without delivering any body data, and the loop starts a new full countdown. A client that sends one of these 9-byte frames before each countdown expires keeps read_body blocked, together with the stream process and whatever the application holds while reading, for as long as it likes.\n\nThis issue affects bandit: from 1.4.0 before 1.14.0."
            }
          ],
          "impacts": [
            {
              "capecId": "CAPEC-469",
              "descriptions": [
                {
                  "lang": "en",
                  "supportingMedia": [
                    {
                      "base64": false,
                      "type": "text/html",
                      "value": "\u003cp\u003eAn unauthenticated client can keep a Bandit HTTP/2 stream, and whatever its request handler holds while reading the body, occupied indefinitely for 9 bytes per \u003ccode\u003eread_timeout\u003c/code\u003e, and repeat this across many streams and connections. This affects any Bandit server with HTTP/2 enabled whose routes read request bodies, which \u003ccode\u003ePlug.Parsers\u003c/code\u003e does for POST, PUT and PATCH.\u003c/p\u003e"
                    },
                    {
                      "base64": false,
                      "type": "text/markdown",
                      "value": "An unauthenticated client can keep a Bandit HTTP/2 stream, and whatever its request handler holds while reading the body, occupied indefinitely for 9 bytes per `read_timeout`, and repeat this across many streams and connections. This affects any Bandit server with HTTP/2 enabled whose routes read request bodies, which `Plug.Parsers` does for POST, PUT and PATCH."
                    }
                  ],
                  "value": "An unauthenticated client can keep a Bandit HTTP/2 stream, and whatever its request handler holds while reading the body, occupied indefinitely for 9 bytes per read_timeout, and repeat this across many streams and connections. This affects any Bandit server with HTTP/2 enabled whose routes read request bodies, which Plug.Parsers does for POST, PUT and PATCH."
                }
              ]
            }
          ],
          "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-835",
                  "description": "CWE-835 Loop with Unreachable Exit Condition (\u0027Infinite Loop\u0027)",
                  "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:30:24.621Z",
            "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "shortName": "EEF"
          },
          "references": [
            {
              "name": "HTTP/2 WINDOW_UPDATE and SETTINGS frames reset the request body read timeout in Bandit",
              "tags": [
                "vendor-advisory",
                "related"
              ],
              "url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-p2qv-vx88-385x"
            },
            {
              "name": "EEF CNA record for CVE-2026-115269",
              "tags": [
                "related"
              ],
              "url": "https://cna.erlef.org/cves/CVE-2026-115269.html"
            },
            {
              "name": "OSV record EEF-CVE-2026-115269",
              "tags": [
                "related"
              ],
              "url": "https://osv.dev/vulnerability/EEF-CVE-2026-115269"
            },
            {
              "name": "Introducing commit fff06ef in mtrudel/bandit",
              "tags": [
                "related"
              ],
              "url": "https://github.com/mtrudel/bandit/commit/fff06efe3be962b484bd4d3eb339372fda5a231f"
            },
            {
              "name": "Fix commit 220b9df in mtrudel/bandit",
              "tags": [
                "patch"
              ],
              "url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
            }
          ],
          "source": {
            "discovery": "UNKNOWN"
          },
          "title": "HTTP/2 WINDOW_UPDATE and SETTINGS frames reset the request body read timeout in Bandit",
          "workarounds": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eDisable HTTP/2 with \u003ccode\u003ehttp_2_options: [enabled: false]\u003c/code\u003e, so that the vulnerable read path never runs.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "Disable HTTP/2 with `http_2_options: [enabled: false]`, so that the vulnerable read path never runs."
                }
              ],
              "value": "Disable HTTP/2 with http_2_options: [enabled: false], so that the vulnerable read path never runs."
            }
          ],
          "x_proofOfConcept": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003col\u003e\n\u003cli\u003eRun Bandit with a Plug that calls \u003ccode\u003ePlug.Conn.read_body/2\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eOpen an HTTP/2 connection and send HEADERS for \u003ccode\u003ePOST /\u003c/code\u003e on stream 1 without END_STREAM.\u003c/li\u003e\n\u003cli\u003eEvery 10 seconds, send a WINDOW_UPDATE on stream 1 with an increment of 1.\u003c/li\u003e\n\u003cli\u003eThe stream stays open for 120 s, eight times the default 15 s \u003ccode\u003eread_timeout\u003c/code\u003e. Without the WINDOW_UPDATE frames, the server ends the read after about 15 s.\u003c/li\u003e\n\u003c/ol\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "1. Run Bandit with a Plug that calls `Plug.Conn.read_body/2`.\n2. Open an HTTP/2 connection and send HEADERS for `POST /` on stream 1 without END_STREAM.\n3. Every 10 seconds, send a WINDOW_UPDATE on stream 1 with an increment of 1.\n4. The stream stays open for 120 s, eight times the default 15 s `read_timeout`. Without the WINDOW_UPDATE frames, the server ends the read after about 15 s."
                }
              ],
              "value": "* Run Bandit with a Plug that calls Plug.Conn.read_body/2.\n* Open an HTTP/2 connection and send HEADERS for POST / on stream 1 without END_STREAM.\n* Every 10 seconds, send a WINDOW_UPDATE on stream 1 with an increment of 1.\n* The stream stays open for 120 s, eight times the default 15 s read_timeout. Without the WINDOW_UPDATE frames, the server ends the read after about 15 s."
            }
          ],
          "x_technicalAnalysis": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003e\u003cstrong\u003e1. Per-receive timeout.\u003c/strong\u003e \u003ccode\u003eBandit.HTTP2.Stream.read_data/2\u003c/code\u003e passes a flat \u003ccode\u003eread_timeout\u003c/code\u003e (default 15,000 ms) to \u003ccode\u003edo_read_data/4\u003c/code\u003e, which blocks in \u003ccode\u003edo_recv/2\u003c/code\u003e\u0027s \u003ccode\u003ereceive ... after timeout\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Non-progress frames end the wait.\u003c/strong\u003e A stream WINDOW_UPDATE, delivered through \u003ccode\u003eBandit.HTTP2.Connection.handle_frame/3\u003c/code\u003e, or an empty SETTINGS frame, which delivers a zero-delta window update to every stream, is matched inside that \u003ccode\u003ereceive\u003c/code\u003e. \u003ccode\u003edo_recv_send_window_update/2\u003c/code\u003e returns a bare \u003ccode\u003e%Stream{}\u003c/code\u003e, and \u003ccode\u003edo_read_data/4\u003c/code\u003e recurses with the identical \u003ccode\u003etimeout\u003c/code\u003e, restarting the countdown.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Nothing else bounds the read.\u003c/strong\u003e The transport read timeout fires only when no bytes arrive, \u003ccode\u003emax_bytes\u003c/code\u003e is decremented only by DATA frames, and neither WINDOW_UPDATE nor SETTINGS frames are rate limited. The send path in \u003ccode\u003edo_send_data/4\u003c/code\u003e uses a progress-based deadline; the read path does not.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "**1. Per-receive timeout.** `Bandit.HTTP2.Stream.read_data/2` passes a flat `read_timeout` (default 15,000 ms) to `do_read_data/4`, which blocks in `do_recv/2`\u0027s `receive ... after timeout`.\n\n**2. Non-progress frames end the wait.** A stream WINDOW_UPDATE, delivered through `Bandit.HTTP2.Connection.handle_frame/3`, or an empty SETTINGS frame, which delivers a zero-delta window update to every stream, is matched inside that `receive`. `do_recv_send_window_update/2` returns a bare `%Stream{}`, and `do_read_data/4` recurses with the identical `timeout`, restarting the countdown.\n\n**3. Nothing else bounds the read.** The transport read timeout fires only when no bytes arrive, `max_bytes` is decremented only by DATA frames, and neither WINDOW_UPDATE nor SETTINGS frames are rate limited. The send path in `do_send_data/4` uses a progress-based deadline; the read path does not."
                }
              ],
              "value": "1. Per-receive timeout. Bandit.HTTP2.Stream.read_data/2 passes a flat read_timeout (default 15,000 ms) to do_read_data/4, which blocks in do_recv/2\u0027s receive ... after timeout.\n\n2. Non-progress frames end the wait. A stream WINDOW_UPDATE, delivered through Bandit.HTTP2.Connection.handle_frame/3, or an empty SETTINGS frame, which delivers a zero-delta window update to every stream, is matched inside that receive. do_recv_send_window_update/2 returns a bare %Stream{}, and do_read_data/4 recurses with the identical timeout, restarting the countdown.\n\n3. Nothing else bounds the read. The transport read timeout fires only when no bytes arrive, max_bytes is decremented only by DATA frames, and neither WINDOW_UPDATE nor SETTINGS frames are rate limited. The send path in do_send_data/4 uses a progress-based deadline; the read path does not."
            }
          ]
        }
      },
      "cveMetadata": {
        "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "assignerShortName": "EEF",
        "cveId": "CVE-2026-115269",
        "datePublished": "2026-10-26T13:30:24.621Z",
        "dateReserved": "2026-10-23T10:15:01.872Z",
        "dateUpdated": "2026-10-26T15:35:52.079Z",
        "state": "PUBLISHED"
      },
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }
  }
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

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.

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

JSON
Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    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.