CVE-2026-109584 (GCVE-0-2026-109584)

Vulnerability from cvelistv5 – Published: 2026-10-26 13:32 – Updated: 2026-10-26 15:35
VLAI
Title
HTTP/2 cookie crumb join expands a small HPACK header block into an unbounded allocation in Bandit
Summary
Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large cookie value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter's run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost. Bandit.HTTP2.Connection caps only the compressed block (max_header_block_size), and its check of the decoded list against max_header_list_size never fires because that setting defaults to :infinity. combine_cookie_crumbs/1 in lib/bandit/http2/stream.ex then joins every crumb into one binary. This issue affects bandit: from 0.3.3 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:11 UTC
CWE
  • CWE-409 - Improper Handling of Highly Compressed Data (Data Amplification)
Assigner
EEF CNA under the mitre root
CNA scorecard A 97/100 over 352 records in the last 180 days details
Impacted products
Vendor Product Version CPE status
mtrudel bandit Affected: 0.3.3 , < 1.14.0 (semver)
    cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*
Create a notification for this product.
mtrudel bandit Affected: 44bf969cd59851622fb6ee4d16227fbc39a77fb4 , < 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-109584",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "yes"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-26T15:11:12.403348Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-10-26T15:35:51.081Z",
          "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.3",
              "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": "44bf969cd59851622fb6ee4d16227fbc39a77fb4",
              "versionType": "git"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "1.14.0",
                  "versionStartIncluding": "0.3.3",
                  "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:29:49.000Z",
      "descriptions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eImproper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large \u003ccode\u003ecookie\u003c/code\u003e value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eBandit.HTTP2.Connection\u003c/code\u003e caps only the compressed block (\u003ccode\u003emax_header_block_size\u003c/code\u003e), and its check of the decoded list against \u003ccode\u003emax_header_list_size\u003c/code\u003e never fires because that setting defaults to \u003ccode\u003e:infinity\u003c/code\u003e. \u003ccode\u003ecombine_cookie_crumbs/1\u003c/code\u003e in \u003ccode\u003elib/bandit/http2/stream.ex\u003c/code\u003e then joins every crumb into one binary.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 0.3.3 before 1.14.0.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large `cookie` value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\n\n`Bandit.HTTP2.Connection` caps only the compressed block (`max_header_block_size`), and its check of the decoded list against `max_header_list_size` never fires because that setting defaults to `:infinity`. `combine_cookie_crumbs/1` in `lib/bandit/http2/stream.ex` then joins every crumb into one binary.\n\nThis issue affects bandit: from 0.3.3 before 1.14.0."
            }
          ],
          "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large cookie value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\n\nBandit.HTTP2.Connection caps only the compressed block (max_header_block_size), and its check of the decoded list against max_header_list_size never fires because that setting defaults to :infinity. combine_cookie_crumbs/1 in lib/bandit/http2/stream.ex then joins every crumb into one binary.\n\nThis issue affects bandit: from 0.3.3 before 1.14.0."
        }
      ],
      "impacts": [
        {
          "capecId": "CAPEC-491",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eAn unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node\u0027s memory, taking down every application on the node.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "An unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node\u0027s memory, taking down every application on the node."
                }
              ],
              "value": "An unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node\u0027s memory, taking down every application on the node."
            }
          ]
        }
      ],
      "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-409",
              "description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-10-26T13:32:22.359Z",
        "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "shortName": "EEF"
      },
      "references": [
        {
          "name": "HTTP/2 cookie crumb join expands a small HPACK header block into an unbounded allocation in Bandit",
          "tags": [
            "vendor-advisory",
            "related"
          ],
          "url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-7gfj-7gvq-3xqj"
        },
        {
          "name": "EEF CNA record for CVE-2026-109584",
          "tags": [
            "related"
          ],
          "url": "https://cna.erlef.org/cves/CVE-2026-109584.html"
        },
        {
          "name": "OSV record EEF-CVE-2026-109584",
          "tags": [
            "related"
          ],
          "url": "https://osv.dev/vulnerability/EEF-CVE-2026-109584"
        },
        {
          "name": "Introducing commit 44bf969 in mtrudel/bandit",
          "tags": [
            "related"
          ],
          "url": "https://github.com/mtrudel/bandit/commit/44bf969cd59851622fb6ee4d16227fbc39a77fb4"
        },
        {
          "name": "Fix commit 220b9df in mtrudel/bandit",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
        }
      ],
      "source": {
        "discovery": "UNKNOWN"
      },
      "title": "HTTP/2 cookie crumb join expands a small HPACK header block into an unbounded allocation in Bandit",
      "workarounds": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eOn 1.12.2 and later, set a finite decoded header list limit, for example \u003ccode\u003ehttp_2_options: [default_local_settings: [max_header_list_size: 65_536]]\u003c/code\u003e, which resets the stream before the cookie crumbs are joined. 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": "On 1.12.2 and later, set a finite decoded header list limit, for example `http_2_options: [default_local_settings: [max_header_list_size: 65_536]]`, which resets the stream before the cookie crumbs are joined. From 0.7.0, disabling HTTP/2 with `http_2_options: [enabled: false]` removes the vulnerable path."
            }
          ],
          "value": "On 1.12.2 and later, set a finite decoded header list limit, for example http_2_options: [default_local_settings: [max_header_list_size: 65_536]], which resets the stream before the cookie crumbs are joined. 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\u003eAgainst a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte \u003ccode\u003ecookie\u003c/code\u003e stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.\u003c/li\u003e\n\u003cli\u003eSend it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with \u003ccode\u003eEND_HEADERS\u003c/code\u003e on the last.\u003c/li\u003e\n\u003cli\u003eThe request reaches the plug with a \u003ccode\u003ecookie\u003c/code\u003e header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. Against a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte `cookie` stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.\n2. Send it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with `END_HEADERS` on the last.\n3. The request reaches the plug with a `cookie` header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it."
            }
          ],
          "value": "* Against a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte cookie stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.\n* Send it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with END_HEADERS on the last.\n* The request reaches the plug with a cookie header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it."
        }
      ],
      "x_technicalAnalysis": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003e\u003cstrong\u003e1. Compression\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe attacker\u0027s header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte \u003ccode\u003emax_header_block_size\u003c/code\u003e. It inserts one 4,058-byte \u003ccode\u003ecookie\u003c/code\u003e into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. \u003ccode\u003eHPAX.decode\u003c/code\u003e returns a list whose entries all point at the same binary, so decoding itself stays cheap.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Missing decoded limit\u003c/strong\u003e (\u003ccode\u003elib/bandit/http2/connection.ex\u003c/code\u003e, \u003ccode\u003elib/bandit/http2/settings.ex\u003c/code\u003e)\u003c/p\u003e\n\u003cp\u003eAfter decoding, the connection compares \u003ccode\u003eheader_list_size(headers)\u003c/code\u003e against \u003ccode\u003elocal_settings.max_header_list_size\u003c/code\u003e. That setting defaults to \u003ccode\u003e:infinity\u003c/code\u003e, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Expansion\u003c/strong\u003e (\u003ccode\u003elib/bandit/http2/stream.ex\u003c/code\u003e)\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eread_headers\u003c/code\u003e calls \u003ccode\u003ecombine_cookie_crumbs/1\u003c/code\u003e, which joins every crumb with \u003ccode\u003eEnum.map_join/3\u003c/code\u003e into a single binary of about 183 MB before \u003ccode\u003ePlug.call/2\u003c/code\u003e runs. \u003ccode\u003emax_concurrent_streams\u003c/code\u003e also defaults to \u003ccode\u003e:infinity\u003c/code\u003e, so N streams allocate N times as much.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "**1. Compression**\n\nThe attacker\u0027s header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte `max_header_block_size`. It inserts one 4,058-byte `cookie` into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. `HPAX.decode` returns a list whose entries all point at the same binary, so decoding itself stays cheap.\n\n**2. Missing decoded limit** (`lib/bandit/http2/connection.ex`, `lib/bandit/http2/settings.ex`)\n\nAfter decoding, the connection compares `header_list_size(headers)` against `local_settings.max_header_list_size`. That setting defaults to `:infinity`, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.\n\n**3. Expansion** (`lib/bandit/http2/stream.ex`)\n\n`read_headers` calls `combine_cookie_crumbs/1`, which joins every crumb with `Enum.map_join/3` into a single binary of about 183 MB before `Plug.call/2` runs. `max_concurrent_streams` also defaults to `:infinity`, so N streams allocate N times as much."
            }
          ],
          "value": "1. Compression\n\nThe attacker\u0027s header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte max_header_block_size. It inserts one 4,058-byte cookie into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. HPAX.decode returns a list whose entries all point at the same binary, so decoding itself stays cheap.\n\n2. Missing decoded limit (lib/bandit/http2/connection.ex, lib/bandit/http2/settings.ex)\n\nAfter decoding, the connection compares header_list_size(headers) against local_settings.max_header_list_size. That setting defaults to :infinity, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.\n\n3. Expansion (lib/bandit/http2/stream.ex)\n\nread_headers calls combine_cookie_crumbs/1, which joins every crumb with Enum.map_join/3 into a single binary of about 183 MB before Plug.call/2 runs. max_concurrent_streams also defaults to :infinity, so N streams allocate N times as much."
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
    "assignerShortName": "EEF",
    "cveId": "CVE-2026-109584",
    "datePublished": "2026-10-26T13:32:22.359Z",
    "dateReserved": "2026-10-22T10:15:01.793Z",
    "dateUpdated": "2026-10-26T15:35:51.081Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "epss": {
      "cve": "CVE-2026-109584",
      "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": "0.3.3",
                    "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": "44bf969cd59851622fb6ee4d16227fbc39a77fb4",
                    "versionType": "git"
                  }
                ]
              }
            ],
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db"
          }
        ],
        "cveTags": [],
        "descriptions": [
          {
            "lang": "en",
            "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large cookie value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\n\nBandit.HTTP2.Connection caps only the compressed block (max_header_block_size), and its check of the decoded list against max_header_list_size never fires because that setting defaults to :infinity. combine_cookie_crumbs/1 in lib/bandit/http2/stream.ex then joins every crumb into one binary.\n\nThis issue affects bandit: from 0.3.3 before 1.14.0."
          }
        ],
        "id": "CVE-2026-109584",
        "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-109584",
                "options": [
                  {
                    "exploitation": "none"
                  },
                  {
                    "automatable": "yes"
                  },
                  {
                    "technicalImpact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-26T15:11:12.403348Z",
                "version": "2.0.3"
              }
            }
          ]
        },
        "published": "2026-10-26T14:16:25.000",
        "references": [
          {
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "url": "https://cna.erlef.org/cves/CVE-2026-109584.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/44bf969cd59851622fb6ee4d16227fbc39a77fb4"
          },
          {
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-7gfj-7gvq-3xqj"
          },
          {
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "url": "https://osv.dev/vulnerability/EEF-CVE-2026-109584"
          }
        ],
        "sourceIdentifier": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "vulnStatus": "Awaiting Analysis",
        "weaknesses": [
          {
            "description": [
              {
                "lang": "en",
                "value": "CWE-409"
              }
            ],
            "source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "type": "Secondary"
          }
        ]
      }
    },
    "vulnrichment": {
      "containers": {
        "adp": [
          {
            "metrics": [
              {
                "other": {
                  "content": {
                    "id": "CVE-2026-109584",
                    "options": [
                      {
                        "Exploitation": "none"
                      },
                      {
                        "Automatable": "yes"
                      },
                      {
                        "Technical Impact": "partial"
                      }
                    ],
                    "role": "CISA Coordinator",
                    "timestamp": "2026-10-26T15:11:12.403348Z",
                    "version": "2.0.3"
                  },
                  "type": "ssvc"
                }
              }
            ],
            "providerMetadata": {
              "dateUpdated": "2026-10-26T15:32:36.017Z",
              "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.3",
                  "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": "44bf969cd59851622fb6ee4d16227fbc39a77fb4",
                  "versionType": "git"
                }
              ]
            }
          ],
          "cpeApplicability": [
            {
              "nodes": [
                {
                  "cpeMatch": [
                    {
                      "criteria": "cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*",
                      "versionEndExcluding": "1.14.0",
                      "versionStartIncluding": "0.3.3",
                      "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:29:49.000Z",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eImproper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large \u003ccode\u003ecookie\u003c/code\u003e value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eBandit.HTTP2.Connection\u003c/code\u003e caps only the compressed block (\u003ccode\u003emax_header_block_size\u003c/code\u003e), and its check of the decoded list against \u003ccode\u003emax_header_list_size\u003c/code\u003e never fires because that setting defaults to \u003ccode\u003e:infinity\u003c/code\u003e. \u003ccode\u003ecombine_cookie_crumbs/1\u003c/code\u003e in \u003ccode\u003elib/bandit/http2/stream.ex\u003c/code\u003e then joins every crumb into one binary.\u003c/p\u003e\n\u003cp\u003eThis issue affects bandit: from 0.3.3 before 1.14.0.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large `cookie` value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\n\n`Bandit.HTTP2.Connection` caps only the compressed block (`max_header_block_size`), and its check of the decoded list against `max_header_list_size` never fires because that setting defaults to `:infinity`. `combine_cookie_crumbs/1` in `lib/bandit/http2/stream.ex` then joins every crumb into one binary.\n\nThis issue affects bandit: from 0.3.3 before 1.14.0."
                }
              ],
              "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in the HTTP/2 implementation of mtrudel bandit allows an unauthenticated remote attacker to exhaust server memory via a small HPACK-compressed HEADERS block. The block stores one large cookie value in the HPACK dynamic table and then references it tens of thousands of times with 1-byte indexed fields. In the reporter\u0027s run, a 49 KB block made a server with default settings allocate a 183 MB cookie binary before any application code ran, and every concurrent stream can repeat the cost.\n\nBandit.HTTP2.Connection caps only the compressed block (max_header_block_size), and its check of the decoded list against max_header_list_size never fires because that setting defaults to :infinity. combine_cookie_crumbs/1 in lib/bandit/http2/stream.ex then joins every crumb into one binary.\n\nThis issue affects bandit: from 0.3.3 before 1.14.0."
            }
          ],
          "impacts": [
            {
              "capecId": "CAPEC-491",
              "descriptions": [
                {
                  "lang": "en",
                  "supportingMedia": [
                    {
                      "base64": false,
                      "type": "text/html",
                      "value": "\u003cp\u003eAn unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node\u0027s memory, taking down every application on the node.\u003c/p\u003e"
                    },
                    {
                      "base64": false,
                      "type": "text/markdown",
                      "value": "An unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node\u0027s memory, taking down every application on the node."
                    }
                  ],
                  "value": "An unauthenticated remote client can make any Bandit server with default HTTP/2 settings allocate a cookie binary thousands of times larger than the header block it sent, before any application code runs. Repeating it across concurrent streams exhausts the BEAM node\u0027s memory, taking down every application on the node."
                }
              ]
            }
          ],
          "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-409",
                  "description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
                  "lang": "en",
                  "type": "CWE"
                }
              ]
            }
          ],
          "providerMetadata": {
            "dateUpdated": "2026-10-26T13:32:22.359Z",
            "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
            "shortName": "EEF"
          },
          "references": [
            {
              "name": "HTTP/2 cookie crumb join expands a small HPACK header block into an unbounded allocation in Bandit",
              "tags": [
                "vendor-advisory",
                "related"
              ],
              "url": "https://github.com/mtrudel/bandit/security/advisories/GHSA-7gfj-7gvq-3xqj"
            },
            {
              "name": "EEF CNA record for CVE-2026-109584",
              "tags": [
                "related"
              ],
              "url": "https://cna.erlef.org/cves/CVE-2026-109584.html"
            },
            {
              "name": "OSV record EEF-CVE-2026-109584",
              "tags": [
                "related"
              ],
              "url": "https://osv.dev/vulnerability/EEF-CVE-2026-109584"
            },
            {
              "name": "Introducing commit 44bf969 in mtrudel/bandit",
              "tags": [
                "related"
              ],
              "url": "https://github.com/mtrudel/bandit/commit/44bf969cd59851622fb6ee4d16227fbc39a77fb4"
            },
            {
              "name": "Fix commit 220b9df in mtrudel/bandit",
              "tags": [
                "patch"
              ],
              "url": "https://github.com/mtrudel/bandit/commit/220b9dfd27f9a21305be2afc75cbe585ddc24e7a"
            }
          ],
          "source": {
            "discovery": "UNKNOWN"
          },
          "title": "HTTP/2 cookie crumb join expands a small HPACK header block into an unbounded allocation in Bandit",
          "workarounds": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eOn 1.12.2 and later, set a finite decoded header list limit, for example \u003ccode\u003ehttp_2_options: [default_local_settings: [max_header_list_size: 65_536]]\u003c/code\u003e, which resets the stream before the cookie crumbs are joined. 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": "On 1.12.2 and later, set a finite decoded header list limit, for example `http_2_options: [default_local_settings: [max_header_list_size: 65_536]]`, which resets the stream before the cookie crumbs are joined. From 0.7.0, disabling HTTP/2 with `http_2_options: [enabled: false]` removes the vulnerable path."
                }
              ],
              "value": "On 1.12.2 and later, set a finite decoded header list limit, for example http_2_options: [default_local_settings: [max_header_list_size: 65_536]], which resets the stream before the cookie crumbs are joined. 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\u003eAgainst a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte \u003ccode\u003ecookie\u003c/code\u003e stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.\u003c/li\u003e\n\u003cli\u003eSend it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with \u003ccode\u003eEND_HEADERS\u003c/code\u003e on the last.\u003c/li\u003e\n\u003cli\u003eThe request reaches the plug with a \u003ccode\u003ecookie\u003c/code\u003e header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it.\u003c/li\u003e\n\u003c/ol\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "1. Against a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte `cookie` stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.\n2. Send it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with `END_HEADERS` on the last.\n3. The request reaches the plug with a `cookie` header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it."
                }
              ],
              "value": "* Against a Bandit server with default HTTP/2 settings, build an HPACK header block with the request pseudo-headers plus a 4,058-byte cookie stored in the dynamic table and then referenced about 45,000 times with indexed representations. The block is about 49 KB.\n* Send it on one stream as a HEADERS frame followed by CONTINUATION frames of at most 16,384 bytes, with END_HEADERS on the last.\n* The request reaches the plug with a cookie header of about 183 MB, and VM memory grows by about the same amount. Repeat on further streams to multiply it."
            }
          ],
          "x_technicalAnalysis": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003e\u003cstrong\u003e1. Compression\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe attacker\u0027s header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte \u003ccode\u003emax_header_block_size\u003c/code\u003e. It inserts one 4,058-byte \u003ccode\u003ecookie\u003c/code\u003e into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. \u003ccode\u003eHPAX.decode\u003c/code\u003e returns a list whose entries all point at the same binary, so decoding itself stays cheap.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Missing decoded limit\u003c/strong\u003e (\u003ccode\u003elib/bandit/http2/connection.ex\u003c/code\u003e, \u003ccode\u003elib/bandit/http2/settings.ex\u003c/code\u003e)\u003c/p\u003e\n\u003cp\u003eAfter decoding, the connection compares \u003ccode\u003eheader_list_size(headers)\u003c/code\u003e against \u003ccode\u003elocal_settings.max_header_list_size\u003c/code\u003e. That setting defaults to \u003ccode\u003e:infinity\u003c/code\u003e, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Expansion\u003c/strong\u003e (\u003ccode\u003elib/bandit/http2/stream.ex\u003c/code\u003e)\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eread_headers\u003c/code\u003e calls \u003ccode\u003ecombine_cookie_crumbs/1\u003c/code\u003e, which joins every crumb with \u003ccode\u003eEnum.map_join/3\u003c/code\u003e into a single binary of about 183 MB before \u003ccode\u003ePlug.call/2\u003c/code\u003e runs. \u003ccode\u003emax_concurrent_streams\u003c/code\u003e also defaults to \u003ccode\u003e:infinity\u003c/code\u003e, so N streams allocate N times as much.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "**1. Compression**\n\nThe attacker\u0027s header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte `max_header_block_size`. It inserts one 4,058-byte `cookie` into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. `HPAX.decode` returns a list whose entries all point at the same binary, so decoding itself stays cheap.\n\n**2. Missing decoded limit** (`lib/bandit/http2/connection.ex`, `lib/bandit/http2/settings.ex`)\n\nAfter decoding, the connection compares `header_list_size(headers)` against `local_settings.max_header_list_size`. That setting defaults to `:infinity`, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.\n\n**3. Expansion** (`lib/bandit/http2/stream.ex`)\n\n`read_headers` calls `combine_cookie_crumbs/1`, which joins every crumb with `Enum.map_join/3` into a single binary of about 183 MB before `Plug.call/2` runs. `max_concurrent_streams` also defaults to `:infinity`, so N streams allocate N times as much."
                }
              ],
              "value": "1. Compression\n\nThe attacker\u0027s header block, split across HEADERS and CONTINUATION frames, stays under the 50,000-byte max_header_block_size. It inserts one 4,058-byte cookie into the 4,096-byte dynamic table, the largest value that fits, then references it about 45,000 times with 1-byte indexed representations. HPAX.decode returns a list whose entries all point at the same binary, so decoding itself stays cheap.\n\n2. Missing decoded limit (lib/bandit/http2/connection.ex, lib/bandit/http2/settings.ex)\n\nAfter decoding, the connection compares header_list_size(headers) against local_settings.max_header_list_size. That setting defaults to :infinity, and in Erlang term order every integer sorts below an atom, so the comparison never rejects a list. The limit is enforced only when an operator sets it.\n\n3. Expansion (lib/bandit/http2/stream.ex)\n\nread_headers calls combine_cookie_crumbs/1, which joins every crumb with Enum.map_join/3 into a single binary of about 183 MB before Plug.call/2 runs. max_concurrent_streams also defaults to :infinity, so N streams allocate N times as much."
            }
          ]
        }
      },
      "cveMetadata": {
        "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "assignerShortName": "EEF",
        "cveId": "CVE-2026-109584",
        "datePublished": "2026-10-26T13:32:22.359Z",
        "dateReserved": "2026-10-22T10:15:01.793Z",
        "dateUpdated": "2026-10-26T15:35:51.081Z",
        "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
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.

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.