Common Weakness Enumeration

CWE-248

Allowed

Uncaught Exception

Abstraction: Base · Status: Draft

An exception is thrown from a function, but it is not caught.

610 vulnerabilities reference this CWE, most recent first.

GHSA-22WV-V5WX-CM9X

Vulnerability from github – Published: 2026-07-18 15:31 – Updated: 2026-07-18 15:31
VLAI
Details

SurrealDB versions before 1.1.1 fail to properly validate invocation of custom parameters and functions at root or namespace levels, causing server panic. Authorized clients can invoke these entities at unsupported levels to crash the SurrealDB server, resulting in denial of service.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-58369"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-18T14:17:10Z",
    "severity": "HIGH"
  },
  "details": "SurrealDB versions before 1.1.1 fail to properly validate invocation of custom parameters and functions at root or namespace levels, causing server panic. Authorized clients can invoke these entities at unsupported levels to crash the SurrealDB server, resulting in denial of service.",
  "id": "GHSA-22wv-v5wx-cm9x",
  "modified": "2026-07-18T15:31:49Z",
  "published": "2026-07-18T15:31:49Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/surrealdb/surrealdb/security/advisories/GHSA-jm4v-58r5-66hj"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-58369"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/surrealdb-before-denial-of-service-via-global-parameters"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-25R4-295R-FVQM

Vulnerability from github – Published: 2022-05-24 16:56 – Updated: 2026-05-29 15:30
VLAI
Details

A CWE-248: Uncaught Exception vulnerability exists in Modicon M580 (firmware version prior to V2.90) and Modicon M340 (firmware version prior to V3.10), which could cause a possible denial of service when writing to specific memory addresses in the controller over Modbus.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2019-6829"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248",
      "CWE-755"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-09-17T20:15:00Z",
    "severity": "HIGH"
  },
  "details": "A CWE-248: Uncaught Exception vulnerability exists in Modicon M580 (firmware version prior to V2.90) and Modicon M340 (firmware version prior to V3.10), which could cause a possible denial of service when writing to specific memory addresses in the controller over Modbus.",
  "id": "GHSA-25r4-295r-fvqm",
  "modified": "2026-05-29T15:30:21Z",
  "published": "2022-05-24T16:56:24Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-6829"
    },
    {
      "type": "WEB",
      "url": "https://www.schneider-electric.com/en/download/document/SEVD-2019-134-11"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-27JF-22P2-6VQ4

Vulnerability from github – Published: 2023-08-29 09:30 – Updated: 2024-04-04 07:15
VLAI
Details

Motorola EBTS/MBTS Site Controller drops to debug prompt on unhandled exception. The Motorola MBTS Site Controller exposes a debug prompt on the device's serial port in case of an unhandled exception. This allows an attacker with physical access that is able to trigger such an exception to extract secret key material and/or gain arbitrary code execution on the device.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-23774"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248",
      "CWE-703",
      "CWE-755"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-08-29T09:15:09Z",
    "severity": "HIGH"
  },
  "details": "Motorola EBTS/MBTS Site Controller drops to debug prompt on unhandled exception. The Motorola MBTS Site Controller exposes a debug prompt on the device\u0027s serial port in case of an unhandled exception. This allows an attacker with physical access that is able to trigger such an exception to extract secret key material and/or gain arbitrary code execution on the device.",
  "id": "GHSA-27jf-22p2-6vq4",
  "modified": "2024-04-04T07:15:16Z",
  "published": "2023-08-29T09:30:24Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-23774"
    },
    {
      "type": "WEB",
      "url": "https://tetraburst.com"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-2823-QMQ8-RWVJ

Vulnerability from github – Published: 2026-10-05 23:42 – Updated: 2026-10-05 23:42
VLAI
Summary
vLLM: Loose `cache_salt` validation lets a single request kill EngineCore on LMCache-MP deployments — uncaught downstream `ValueError` denial of service
Details

Affected

  • Ecosystem / package: pip / vllm
  • Affected versions: vLLM ≤ 0.25.1 (confirmed on 0.25.1, commit 752a3a504485). The lower bound predates 0.25.1; maintainers can confirm how far back the loose cache_salt validator and unguarded scheduling-path lookup reach.

Summary

vLLM's OpenAI-compatible request models (Completions, Chat Completions, Responses) accept a client-supplied cache_salt field and validate it only as "must be a non-empty string" — no character or length restrictions. On a deployment with the built-in LMCache-MP KV connector enabled, that value is stored verbatim on the request tracker and forwarded unguarded as a keyword argument into the scheduler's per-step cache lookup. The downstream LMCache library applies a stricter check in IPCCacheServerKey.__post_init__, which raises ValueError for any cache_salt containing @, /, \, or NUL (or longer than 128 characters).

Neither the LMCache-MP connector lookup call site nor Scheduler.schedule() wraps that call in a request-scoped try/except, so the ValueError propagates uncaught into EngineCore's top-level handler, which treats any uncaught exception as fatal and kills the whole engine process. A single publicly reachable request with, for example, cache_salt="/" therefore takes down the engine for all concurrent users. vLLM's boundary validator is looser than the downstream consumer's, and the gap is never converted into a request-scoped failure on the scheduling path.

Affected code

Links pinned to the confirmed commit 752a3a504485 (v0.25.1):

The three OpenAI check_cache_salt_support validators are identical; the completion one is representative — a non-empty-string test with no character or length bound:

# vllm/entrypoints/openai/completion/protocol.py Lines 503-509
        if data.get("cache_salt") is not None and (
            not isinstance(data["cache_salt"], str) or not data["cache_salt"]
        ):
            raise VLLMValidationError(
                "Parameter 'cache_salt' must be a non-empty string if provided.",
                parameter="cache_salt",
            )

On the scheduling path the connector is invoked with no surrounding try — a ValueError from the downstream salt check propagates straight out of schedule():

# vllm/v1/core/sched/scheduler.py Lines 736-742
                    # Get externally-cached tokens if using a KVConnector.
                    if self.connector is not None:
                        ext_tokens, load_kv_async = (
                            self.connector.get_num_new_matched_tokens(
                                request, num_new_local_computed_tokens
                            )
                        )

run_engine_core's generic handler — the next except up the stack — treats that as fatal, marks the engine dead, and re-raises:

# vllm/v1/engine/core.py Lines 1229-1235
        except Exception as e:
            if engine_core is None:
                logger.exception("EngineCore failed to start.")
            else:
                logger.exception("EngineCore encountered a fatal error.")
                engine_core._send_engine_dead()
            raise e

Impact

Availability only. cache_salt is an attacker-controlled, publicly reachable request field that vLLM validates too loosely. A value such as "/" passes vLLM's check, reaches the stricter downstream validator, and its ValueError is never converted into a request-scoped failure — instead it kills the EngineCore process, a denial of service for every concurrent request on that server (HTTP failures, then /health failing).

Applicability: the built-in LMCache-MP KV connector must be enabled (lmcache >= 0.4.4), which is itself an opt-in KV-connector boundary. On such deployments no other special configuration is required, and the crash is a resource-availability failure rather than expected behavior of the opt-in feature.

Suggested Fix

Two independent fixes:

  1. Tighten admission — add one shared validate_cache_salt() helper (for example in vllm/entrypoints/openai/engine/protocol.py) that matches or exceeds the downstream IPCCacheServerKey rules — reject @, /, \, NUL, and >128-character salts at the HTTP boundary with a 4xx — and route every request model that exposes cache_salt through it: the three check_cache_salt_support validators above, the pooling base request, and the token-in-token-out GenerateRequest (which has no validator today).
  2. Defense in depth — wrap the LMCache-MP lookup call reached from Scheduler.schedule() so a downstream validator ValueError becomes a request-scoped failure instead of an EngineCore-fatal exception. This is the fix that also covers future divergence between vLLM's and LMCache's salt rules; the right failure semantics (fail the request vs. fall back to a cold lookup) is a maintainer design call.

The core of fix 1 is a single shared helper; each check_cache_salt_support body then becomes validate_cache_salt(data.get("cache_salt")), and GenerateRequest gains an equivalent mode="before" validator:

# vllm/entrypoints/openai/engine/protocol.py — new shared helper
_CACHE_SALT_FORBIDDEN_CHARS = frozenset("@/\\\x00")
_MAX_CACHE_SALT_LENGTH = 128


def validate_cache_salt(cache_salt: object) -> None:
    """Validate cache salts before they reach downstream cache backends."""
    if cache_salt is None:
        return
    if not isinstance(cache_salt, str) or not cache_salt:
        raise VLLMValidationError(
            "Parameter 'cache_salt' must be a non-empty string if provided.",
            parameter="cache_salt",
        )
    if len(cache_salt) > _MAX_CACHE_SALT_LENGTH or any(
        char in _CACHE_SALT_FORBIDDEN_CHARS for char in cache_salt
    ):
        raise VLLMValidationError(
            "Parameter 'cache_salt' must be at most 128 characters and must "
            "not contain '@', '/', '\\\\', or NUL.",
            parameter="cache_salt",
        )

This distinguishes the finding from GHSA-6qc9-v4r8-22xg: that advisory fixed only the guided_json/xgrammar trigger of the same schedule()-into-run_engine_core fatal-handler family, so the cache_salt admission gap and the schedule()-level defense-in-depth (fix 2) survive its published fix. A patch implementing fix 1 across all five request models, with a regression test covering the rejected ("/", 129-char) and accepted salt shapes, applies to v0.25.1 with line offsets and no fuzz.

Credit

Reported by: Patch the Planet (Trail of Bits + OpenAI collaboration)

This vulnerability was discovered using GPT-5.5-Cyber as part of the Patch the Planet security initiative.


Proposed fix: a fix for this issue is proposed in a public pull request: https://github.com/vllm-project/vllm/pull/51444

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "vllm"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.30.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-105756"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-248"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-05T23:42:34Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Affected\n\n- **Ecosystem / package:** pip / `vllm`\n- **Affected versions:** vLLM \u2264 0.25.1 (confirmed on 0.25.1, commit [`752a3a504485`](https://github.com/vllm-project/vllm/tree/752a3a504485790a2e8491cacbb35c137339ad34)). The lower bound predates 0.25.1; maintainers can confirm how far back the loose `cache_salt` validator and unguarded scheduling-path lookup reach.\n\n## Summary\n\nvLLM\u0027s OpenAI-compatible request models (Completions, Chat Completions, Responses) accept a client-supplied `cache_salt` field and validate it only as \"must be a non-empty string\" \u2014 no character or length restrictions. On a deployment with the built-in LMCache-MP KV connector enabled, that value is stored verbatim on the request tracker and forwarded unguarded as a keyword argument into the scheduler\u0027s per-step cache lookup. The downstream LMCache library applies a *stricter* check in `IPCCacheServerKey.__post_init__`, which raises `ValueError` for any `cache_salt` containing `@`, `/`, `\\`, or NUL (or longer than 128 characters).\n\nNeither the LMCache-MP connector lookup call site nor `Scheduler.schedule()` wraps that call in a request-scoped `try`/`except`, so the `ValueError` propagates uncaught into `EngineCore`\u0027s top-level handler, which treats any uncaught exception as fatal and kills the whole engine process. A single publicly reachable request with, for example, `cache_salt=\"/\"` therefore takes down the engine for all concurrent users. vLLM\u0027s boundary validator is looser than the downstream consumer\u0027s, and the gap is never converted into a request-scoped failure on the scheduling path.\n\n## Affected code\n\nLinks pinned to the confirmed commit [`752a3a504485`](https://github.com/vllm-project/vllm/tree/752a3a504485790a2e8491cacbb35c137339ad34) (v0.25.1):\n\n- The three `check_cache_salt_support` validators require only a non-empty string \u2014 no character or length bound: [`vllm/entrypoints/openai/completion/protocol.py#L502-L508`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/completion/protocol.py#L502-L508) (field at [`#L172`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/completion/protocol.py#L172)), [`vllm/entrypoints/openai/chat_completion/protocol.py#L913-L919`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/chat_completion/protocol.py#L913-L919) (field at [`#L425`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/chat_completion/protocol.py#L425)), and [`vllm/entrypoints/openai/responses/protocol.py#L459-L465`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/responses/protocol.py#L459-L465) (field at [`#L235`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/responses/protocol.py#L235)). The loose test itself is at [`completion #L503-L505`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/completion/protocol.py#L503-L505), [`chat_completion #L914-L916`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/chat_completion/protocol.py#L914-L916), [`responses #L460-L462`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/openai/responses/protocol.py#L460-L462).\n- Two further request models accept `cache_salt` with the same or weaker checking, and should be hardened at the same time: [`vllm/entrypoints/pooling/base/protocol.py#L74-L85`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/pooling/base/protocol.py#L74-L85) carries the identical non-empty-string-only validator (field at [`#L59`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/pooling/base/protocol.py#L59)), and the token-in-token-out scale-out `GenerateRequest` exposes the field with **no** `cache_salt` validator at all: [`vllm/entrypoints/scale_out/token_in_token_out/protocol.py#L110`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/entrypoints/scale_out/token_in_token_out/protocol.py#L110).\n- The LMCache-MP request tracker stores the salt verbatim: [`vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py#L189`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py#L189) (`LMCacheMPRequestTracker`), assignment at [`#L223`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py#L223).\n- The lookup call forwards `cache_salt` with no surrounding `try`: [`vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py#L733-L774`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py#L733-L774) (`get_num_new_matched_tokens` \u2192 `maybe_submit_lookup_request(...)` at [`#L770`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py#L770)).\n- The scheduler invokes the connector unguarded: [`vllm/v1/core/sched/scheduler.py#L739`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/v1/core/sched/scheduler.py#L739) (`self.connector.get_num_new_matched_tokens(...)`, inside [`schedule()` at #L396](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/v1/core/sched/scheduler.py#L396)).\n- The generic top-level handler treats the exception as fatal: [`vllm/v1/engine/core.py#L1229-L1235`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/v1/engine/core.py#L1229-L1235) \u2014 the `except Exception` in `run_engine_core` ([`#L1154`](https://github.com/vllm-project/vllm/blob/752a3a504485790a2e8491cacbb35c137339ad34/vllm/v1/engine/core.py#L1154)) logs `EngineCore encountered a fatal error.`, calls `_send_engine_dead()`, and re-raises.\n- Downstream strict validator (external LMCache library, not vLLM): `IPCCacheServerKey.__post_init__` in `lmcache/v1/multiprocess/custom_types.py` rejects `@ / \\` NUL and \u003e128-char salts (`_SALT_FORBIDDEN_CHARS = frozenset(\"@/\\\\\\x00\")`) by raising `ValueError`.\n\nThe three OpenAI `check_cache_salt_support` validators are identical; the completion one is representative \u2014 a non-empty-string test with no character or length bound:\n\n```python\n# vllm/entrypoints/openai/completion/protocol.py Lines 503-509\n        if data.get(\"cache_salt\") is not None and (\n            not isinstance(data[\"cache_salt\"], str) or not data[\"cache_salt\"]\n        ):\n            raise VLLMValidationError(\n                \"Parameter \u0027cache_salt\u0027 must be a non-empty string if provided.\",\n                parameter=\"cache_salt\",\n            )\n```\n\nOn the scheduling path the connector is invoked with no surrounding `try` \u2014 a `ValueError` from the downstream salt check propagates straight out of `schedule()`:\n\n```python\n# vllm/v1/core/sched/scheduler.py Lines 736-742\n                    # Get externally-cached tokens if using a KVConnector.\n                    if self.connector is not None:\n                        ext_tokens, load_kv_async = (\n                            self.connector.get_num_new_matched_tokens(\n                                request, num_new_local_computed_tokens\n                            )\n                        )\n```\n\n`run_engine_core`\u0027s generic handler \u2014 the next `except` up the stack \u2014 treats that as fatal, marks the engine dead, and re-raises:\n\n```python\n# vllm/v1/engine/core.py Lines 1229-1235\n        except Exception as e:\n            if engine_core is None:\n                logger.exception(\"EngineCore failed to start.\")\n            else:\n                logger.exception(\"EngineCore encountered a fatal error.\")\n                engine_core._send_engine_dead()\n            raise e\n```\n\n## Impact\n\nAvailability only. `cache_salt` is an attacker-controlled, publicly reachable request field that vLLM validates too loosely. A value such as `\"/\"` passes vLLM\u0027s check, reaches the stricter downstream validator, and its `ValueError` is never converted into a request-scoped failure \u2014 instead it kills the EngineCore process, a denial of service for every concurrent request on that server (HTTP failures, then `/health` failing).\n\nApplicability: the built-in LMCache-MP KV connector must be enabled (`lmcache \u003e= 0.4.4`), which is itself an opt-in KV-connector boundary. On such deployments no other special configuration is required, and the crash is a resource-availability failure rather than expected behavior of the opt-in feature.\n\n\n## Suggested Fix\n\nTwo independent fixes:\n\n1. **Tighten admission** \u2014 add one shared `validate_cache_salt()` helper (for example in `vllm/entrypoints/openai/engine/protocol.py`) that matches or exceeds the downstream `IPCCacheServerKey` rules \u2014 reject `@`, `/`, `\\`, NUL, and \u003e128-character salts at the HTTP boundary with a 4xx \u2014 and route every request model that exposes `cache_salt` through it: the three `check_cache_salt_support` validators above, the pooling base request, and the token-in-token-out `GenerateRequest` (which has no validator today).\n2. **Defense in depth** \u2014 wrap the LMCache-MP lookup call reached from `Scheduler.schedule()` so a downstream validator `ValueError` becomes a request-scoped failure instead of an EngineCore-fatal exception. This is the fix that also covers future divergence between vLLM\u0027s and LMCache\u0027s salt rules; the right failure semantics (fail the request vs. fall back to a cold lookup) is a maintainer design call.\n\nThe core of fix 1 is a single shared helper; each `check_cache_salt_support` body then becomes `validate_cache_salt(data.get(\"cache_salt\"))`, and `GenerateRequest` gains an equivalent `mode=\"before\"` validator:\n\n```python\n# vllm/entrypoints/openai/engine/protocol.py \u2014 new shared helper\n_CACHE_SALT_FORBIDDEN_CHARS = frozenset(\"@/\\\\\\x00\")\n_MAX_CACHE_SALT_LENGTH = 128\n\n\ndef validate_cache_salt(cache_salt: object) -\u003e None:\n    \"\"\"Validate cache salts before they reach downstream cache backends.\"\"\"\n    if cache_salt is None:\n        return\n    if not isinstance(cache_salt, str) or not cache_salt:\n        raise VLLMValidationError(\n            \"Parameter \u0027cache_salt\u0027 must be a non-empty string if provided.\",\n            parameter=\"cache_salt\",\n        )\n    if len(cache_salt) \u003e _MAX_CACHE_SALT_LENGTH or any(\n        char in _CACHE_SALT_FORBIDDEN_CHARS for char in cache_salt\n    ):\n        raise VLLMValidationError(\n            \"Parameter \u0027cache_salt\u0027 must be at most 128 characters and must \"\n            \"not contain \u0027@\u0027, \u0027/\u0027, \u0027\\\\\\\\\u0027, or NUL.\",\n            parameter=\"cache_salt\",\n        )\n```\n\nThis distinguishes the finding from **[GHSA-6qc9-v4r8-22xg](https://github.com/vllm-project/vllm/security/advisories/GHSA-6qc9-v4r8-22xg)**: that advisory fixed only the `guided_json`/`xgrammar` trigger of the same `schedule()`-into-`run_engine_core` fatal-handler family, so the `cache_salt` admission gap and the `schedule()`-level defense-in-depth (fix 2) survive its published fix. A patch implementing fix 1 across all five request models, with a regression test covering the rejected (`\"/\"`, 129-char) and accepted salt shapes, applies to v0.25.1 with line offsets and no fuzz.\n\n## Credit\n\n**Reported by:** Patch the Planet (Trail of Bits + OpenAI collaboration)\n\nThis vulnerability was discovered using GPT-5.5-Cyber as part of the Patch the Planet security initiative.\n\n---\n\n**Proposed fix:** a fix for this issue is proposed in a public pull request: https://github.com/vllm-project/vllm/pull/51444",
  "id": "GHSA-2823-qmq8-rwvj",
  "modified": "2026-10-05T23:42:34Z",
  "published": "2026-10-05T23:42:34Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/security/advisories/GHSA-2823-qmq8-rwvj"
    },
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/pull/51444"
    },
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/commit/e962733e08d10f7ca65dac4df99e116460b8b174"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/vllm-project/vllm"
    },
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/releases/tag/v0.30.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "vLLM: Loose `cache_salt` validation lets a single request kill EngineCore on LMCache-MP deployments \u2014 uncaught downstream `ValueError` denial of service"
}

GHSA-29X4-R6JV-FF4W

Vulnerability from github – Published: 2026-04-18 01:15 – Updated: 2026-05-12 13:33
VLAI
Summary
Zebra Vulnerable to Denial of Service via Interrupted JSON-RPC Requests from Authenticated Clients
Details

A vulnerability in Zebra's JSON-RPC HTTP middleware allows an authenticated RPC client to cause a Zebra node to crash by disconnecting before the request body is fully received. The node treats the failure to read the HTTP request body as an unrecoverable error and aborts the process instead of returning an error response.

Severity

Moderate - This is a Denial of Service (DoS) that requires a client capable of passing Zebra's cookie authentication, which is enabled by default.

Affected Versions

  • zebrad: versions from 2.2.0 up to (but not including) 4.3.1
  • zebra-rpc: versions from 1.0.0-beta.45 up to (but not including) 6.0.2

Description

Zebra's JSON-RPC HTTP middleware treated a failure to read the incoming HTTP request body as an unrecoverable error, aborting the process rather than returning an error response. A client that disconnected after sending only part of a request body, for example, by resetting the TCP connection mid-transfer, was sufficient to trigger the crash. The vulnerability could be exploited only by authenticated RPC clients. Nodes running the shipped defaults, with RPC bound to localhost and cookie authentication on, were not vulnerable.

Impact

Denial of Service * Attack Vector: Network, authenticated (requires a valid RPC cookie when cookie authentication is enabled). * Effect: Immediate crash of the Zebra node. * Scope: Any node whose RPC interface is reachable by a client with valid credentials, or any node with cookie authentication disabled and an exposed RPC interface.

Fixed Versions

This issue is fixed in Zebra 4.3.1 (crate zebra-rpc 6.0.2).

The fix propagates failures to read the HTTP request body as ordinary error responses, so Zebra now rejects truncated or interrupted requests rather than crashing.

Mitigation

Users should upgrade to Zebra 4.3.1 or later.

If an immediate upgrade is not possible, users should ensure their RPC port is not exposed to untrusted networks and that cookie authentication remains enabled (the default).

References

Credits

Thanks to shieldedonly who discovered this issue and reported it via our coordinated disclosure process.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "zebra-rpc"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.0.0-beta.45"
            },
            {
              "fixed": "6.0.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "zebrad"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.2.0"
            },
            {
              "fixed": "4.3.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41585"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248",
      "CWE-617"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-18T01:15:10Z",
    "nvd_published_at": "2026-05-08T15:16:41Z",
    "severity": "MODERATE"
  },
  "details": "A vulnerability in Zebra\u0027s JSON-RPC HTTP middleware allows an authenticated RPC client to cause a Zebra node to crash by disconnecting before the request body is fully received. The node treats the failure to read the HTTP request body as an unrecoverable error and aborts the process instead of returning an error response.\n\n## Severity\n**Moderate** - This is a Denial of Service (DoS) that requires a client capable of passing Zebra\u0027s cookie authentication, which is enabled by default.\n\n## Affected Versions\n- `zebrad`: versions from **2.2.0** up to (but not including) **4.3.1**\n- `zebra-rpc`: versions from **1.0.0-beta.45** up to (but not including) **6.0.2**\n\n## Description\n\nZebra\u0027s JSON-RPC HTTP middleware treated a failure to read the incoming HTTP request body as an unrecoverable error, aborting the process rather than returning an error response. A client that disconnected after sending only part of a request body, for example, by resetting the TCP connection mid-transfer, was sufficient to trigger the crash. The vulnerability could be exploited only by authenticated RPC clients. Nodes running the shipped defaults, with RPC bound to localhost and cookie authentication on, were not vulnerable.\n\n## Impact\n**Denial of Service**\n* **Attack Vector:** Network, authenticated (requires a valid RPC cookie when cookie authentication is enabled).\n* **Effect:** Immediate crash of the Zebra node.\n* **Scope:** Any node whose RPC interface is reachable by a client with valid credentials, or any node with cookie authentication disabled and an exposed RPC interface.\n\n## Fixed Versions\nThis issue is fixed in **Zebra 4.3.1** (crate `zebra-rpc` 6.0.2).\n\nThe fix propagates failures to read the HTTP request body as ordinary error responses, so Zebra now rejects truncated or interrupted requests rather than crashing.\n\n## Mitigation\nUsers should upgrade to **Zebra 4.3.1** or later.\n\nIf an immediate upgrade is not possible, users should ensure their RPC port is not exposed to untrusted networks and that cookie authentication remains enabled (the default).\n\n## References\n* [Zebra 4.3.1 Release Announcement](https://zfnd.org/)\n\n## Credits\nThanks to [shieldedonly](https://github.com/shieldedonly) who discovered this issue and reported it via our coordinated disclosure process.",
  "id": "GHSA-29x4-r6jv-ff4w",
  "modified": "2026-05-12T13:33:49Z",
  "published": "2026-04-18T01:15:10Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ZcashFoundation/zebra/security/advisories/GHSA-29x4-r6jv-ff4w"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41585"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ZcashFoundation/zebra"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:H",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Zebra Vulnerable to Denial of Service via Interrupted JSON-RPC Requests from Authenticated Clients"
}

GHSA-2C5J-956X-XMG8

Vulnerability from github – Published: 2026-07-07 06:31 – Updated: 2026-07-07 06:31
VLAI
Details

Uncaught Exception (CWE-248) in the Controller 6000 and Controller 7000 diagnostic web interface allows an authenticated and authorized operator to trigger a Controller restart by sending specific requests, resulting in a temporary denial of service.  Version of Command Centre affected:

  • 9.50 prior to vCR9.50.260616a (distributed in 9.50.1587(MR1))
  • 9.40 prior to vCR9.40.260616a (distributed in 9.40.3130(MR3))
  • 9.30 prior to vCR9.30.260616a (distributed in 9.30.3983(MR5))
  • 9.20 prior to vCR9.20.260616a (distributed in 9.20.4349(MR7))
  • all versions of 9.10 and prior.
Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-27844"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-07T05:16:50Z",
    "severity": "LOW"
  },
  "details": "Uncaught Exception (CWE-248)\u00a0in the Controller 6000 and Controller 7000 diagnostic web interface allows an authenticated and authorized operator to trigger a Controller restart by sending specific requests, resulting in a temporary denial of service.\u00a0\nVersion of Command Centre affected:\n\n\n\n\n\n  *  9.50 prior to vCR9.50.260616a (distributed in 9.50.1587(MR1))\n  *  9.40 prior to vCR9.40.260616a (distributed in\u00a09.40.3130(MR3))\n  *  9.30 prior to vCR9.30.260616a (distributed in 9.30.3983(MR5))\n  *  9.20 prior to vCR9.20.260616a (distributed in 9.20.4349(MR7))\n  *  all versions of 9.10 and prior.",
  "id": "GHSA-2c5j-956x-xmg8",
  "modified": "2026-07-07T06:31:24Z",
  "published": "2026-07-07T06:31:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27844"
    },
    {
      "type": "WEB",
      "url": "https://security.gallagher.com/en-NZ/Security-Advisories/CVE-2026-27844"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-2GC4-CQFQ-P2GV

Vulnerability from github – Published: 2026-09-29 23:44 – Updated: 2026-09-29 23:44
VLAI
Summary
Socket.IO: Engine.IO Protocol Revision Mismatch DoS
Details

Impact

A denial-of-service vulnerability exists in Engine.IO / Socket.IO servers that allow transport upgrades.

The Engine.IO protocol revision is negotiated during the initial handshake and stored on the session, but a newly-created transport, including a WebSocket upgrade transport, could independently derive a different protocol revision from the upgrade request query parameters. The server did not verify that the protocol revision of an upgrade request matched the protocol revision of the existing session.

A malicious client could exploit this mismatch by establishing a valid Engine.IO session and then sending an upgrade request with a different, or omitted, EIO query parameter. This could cause the server to attach a transport using a parser and heartbeat behavior inconsistent with the session. Under some conditions, a crafted heartbeat packet could trigger an uncaught exception and terminate the Node.js process.

Servers using the default Engine.IO v4 protocol are impacted. The issue can be triggered even when Engine.IO v3 compatibility is disabled, because an omitted EIO parameter is interpreted as protocol v3 on the affected transport path.

The impact is denial of service through process crash.

Affected versions:

  • engine.io >= 6.6.0, < 6.6.10

Patches

The issue was fixed in:

  • engine.io 6.6.10

Users should upgrade to engine.io@6.6.10 or later.

If using Socket.IO packages that depend on Engine.IO, users should update to a Socket.IO release that includes the patched Engine.IO version.

Workarounds

If upgrading is not immediately possible, users can reduce exposure by disabling transport upgrades:

const io = new Server(httpServer, {
  allowUpgrades: false
});

or by allowing only a single transport, for example WebSocket only:

const io = new Server(httpServer, {
  transports: ["websocket"]
});

These mitigations avoid the vulnerable upgrade path, but they may affect client compatibility and connection behavior.

As an additional temporary mitigation, deployments may reject Engine.IO requests for an existing sid when the EIO query parameter is missing or does not match the protocol revision used during the initial handshake. This is best done at the application proxy or middleware layer only if the deployment can reliably track the session’s negotiated protocol.

Upgrading remains the recommended fix.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "engine.io"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.6.0"
            },
            {
              "fixed": "6.6.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-102599"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-29T23:44:33Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Impact\n\nA denial-of-service vulnerability exists in Engine.IO / Socket.IO servers that allow transport upgrades.\n\nThe Engine.IO protocol revision is negotiated during the initial handshake and stored on the session, but a newly-created transport, including a WebSocket upgrade transport, could independently derive a different protocol revision from the upgrade request query parameters. The server did not verify that the protocol revision of an upgrade request matched the protocol revision of the existing session.\n\nA malicious client could exploit this mismatch by establishing a valid Engine.IO session and then sending an upgrade request with a different, or omitted, `EIO` query parameter. This could cause the server to attach a transport using a parser and heartbeat behavior inconsistent with the session. Under some conditions, a crafted heartbeat packet could trigger an uncaught exception and terminate the Node.js process.\n\nServers using the default Engine.IO v4 protocol are impacted. The issue can be triggered even when Engine.IO v3 compatibility is disabled, because an omitted `EIO` parameter is interpreted as protocol v3 on the affected transport path.\n\nThe impact is **denial of service** through process crash.\n\nAffected versions:\n\n- `engine.io \u003e= 6.6.0, \u003c 6.6.10`\n\n## Patches\n\nThe issue was fixed in:\n\n- **engine.io 6.6.10**\n\nUsers should upgrade to `engine.io@6.6.10` or later.\n\nIf using Socket.IO packages that depend on Engine.IO, users should update to a Socket.IO release that includes the patched Engine.IO version.\n\n### Workarounds\n\nIf upgrading is not immediately possible, users can reduce exposure by disabling transport upgrades:\n\n```javascript\nconst io = new Server(httpServer, {\n  allowUpgrades: false\n});\n```\n\nor by allowing only a single transport, for example WebSocket only:\n\n```javascript\nconst io = new Server(httpServer, {\n  transports: [\"websocket\"]\n});\n```\n\nThese mitigations avoid the vulnerable upgrade path, but they may affect client compatibility and connection behavior.\n\nAs an additional temporary mitigation, deployments may reject Engine.IO requests for an existing `sid` when the `EIO` query parameter is missing or does not match the protocol revision used during the initial handshake. This is best done at the application proxy or middleware layer only if the deployment can reliably track the session\u2019s negotiated protocol.\n\nUpgrading remains the recommended fix.",
  "id": "GHSA-2gc4-cqfq-p2gv",
  "modified": "2026-09-29T23:44:33Z",
  "published": "2026-09-29T23:44:33Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/socketio/socket.io/security/advisories/GHSA-2gc4-cqfq-p2gv"
    },
    {
      "type": "WEB",
      "url": "https://github.com/socketio/socket.io/commit/86db1fc3db2cd315a065d64c4e48918ccf9b4729"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/socketio/socket.io"
    },
    {
      "type": "WEB",
      "url": "https://github.com/socketio/socket.io/releases/tag/engine.io@6.6.10"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Socket.IO: Engine.IO Protocol Revision Mismatch DoS"
}

GHSA-2GQQ-GQF2-X968

Vulnerability from github – Published: 2026-09-29 18:18 – Updated: 2026-09-29 18:18
VLAI
Summary
undici vulnerable to response truncation via oversized chunked responses in the dump interceptor
Details

Impact

undici's interceptors.dump() reads and discards response bodies up to a configurable maxSize. When a response declares a Content-Length that exceeds maxSize, the request is aborted cleanly. When a response is sent chunked (no Content-Length) and its body exceeds maxSize, it is not aborted: the interceptor ends the response early once the accumulated size reaches maxSize, and continued delivery from the parser triggers an internal assertion that is caught and turned into a request abort and connection tear-down. The application observes a misleading 200 with an empty or truncated body while the connection is disconnected. Any application using the dump interceptor against untrusted or misbehaving upstreams is affected.

Patches

Upgrade to 7.29.1 or 8.10.2. The dump interceptor now enforces maxSize on both the declared and the received body size, aborting the request with a RequestAbortedError instead of returning a truncated response.

Workarounds

None. Avoid using interceptors.dump() with untrusted upstreams until upgraded.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "undici"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.1.0"
            },
            {
              "fixed": "7.29.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "undici"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.0.0"
            },
            {
              "fixed": "8.10.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-84947"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-248"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-29T18:18:51Z",
    "nvd_published_at": "2026-09-04T17:17:02Z",
    "severity": "LOW"
  },
  "details": "### Impact\n\nundici\u0027s `interceptors.dump()` reads and discards response bodies up to a configurable `maxSize`. When a response declares a `Content-Length` that exceeds `maxSize`, the request is aborted cleanly. When a response is sent chunked (no `Content-Length`) and its body exceeds `maxSize`, it is not aborted: the interceptor ends the response early once the accumulated size reaches `maxSize`, and continued delivery from the parser triggers an internal assertion that is caught and turned into a request abort and connection tear-down. The application observes a misleading `200` with an empty or truncated body while the connection is disconnected. Any application using the dump interceptor against untrusted or misbehaving upstreams is affected.\n\n### Patches\n\nUpgrade to `7.29.1` or `8.10.2`. The dump interceptor now enforces `maxSize` on both the declared and the received body size, aborting the request with a `RequestAbortedError` instead of returning a truncated response.\n\n### Workarounds\n\nNone. Avoid using `interceptors.dump()` with untrusted upstreams until upgraded.",
  "id": "GHSA-2gqq-gqf2-x968",
  "modified": "2026-09-29T18:18:51Z",
  "published": "2026-09-29T18:18:51Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nodejs/undici/security/advisories/GHSA-2gqq-gqf2-x968"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-84947"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodejs/undici/commit/21693f406f0142f3504192e9f9b022dcf84782ae"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodejs/undici/commit/6d583124e7cf60b640097d64144ed633cc450584"
    },
    {
      "type": "WEB",
      "url": "https://cna.openjsf.org/security-advisories.html"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nodejs/undici"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodejs/undici/releases/tag/v7.29.1"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodejs/undici/releases/tag/v8.10.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "undici vulnerable to response truncation via oversized chunked responses in the dump interceptor"
}

GHSA-2GW2-QGJG-XH6P

Vulnerability from github – Published: 2025-02-20 20:24 – Updated: 2025-02-20 20:24
VLAI
Summary
Namada-apps allows Post-Genesis Validator Bypass
Details

Impact

Ledger crash. A user is able to initialize a post-genesis validator with a negative commission rate using the --force flag. If this validator gets into the consensus set, then when computing PoS inflation inside fn update_rewards_products_and_mint_inflation, an instance of mul_floor will cause the return of an Err, which causes finalize_block to error.

Patches

This issue has been patched in apps version 1.1.0. The PoS validity predicate now enforces that the commission rate is not negative and any transaction that fails the check will be rejected, both for newly initialized validators and for commission rate change of an existing validator.

Workarounds

There are no workarounds and users are advised to upgrade.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "namada-apps"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.0.0"
            },
            {
              "fixed": "1.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "1.0.0"
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-248"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-02-20T20:24:19Z",
    "nvd_published_at": null,
    "severity": "CRITICAL"
  },
  "details": "### Impact\n\nLedger crash. A user is able to initialize a post-genesis validator with a negative commission rate using the `--force` flag. If this validator gets into the consensus set, then when computing PoS inflation inside `fn update_rewards_products_and_mint_inflation`, an instance of `mul_floor` will cause the return of an `Err`, which causes `finalize_block` to error.\n\n### Patches\n\nThis issue has been patched in apps version 1.1.0. The PoS validity predicate now enforces that the commission rate is not negative and any transaction that fails the check will be rejected, both for newly initialized validators and for commission rate change of an existing validator.\n\n### Workarounds\n\nThere are no workarounds and users are advised to upgrade.",
  "id": "GHSA-2gw2-qgjg-xh6p",
  "modified": "2025-02-20T20:24:19Z",
  "published": "2025-02-20T20:24:19Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/anoma/namada/security/advisories/GHSA-2gw2-qgjg-xh6p"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/anoma/namada"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [],
  "summary": "Namada-apps allows Post-Genesis Validator Bypass"
}

GHSA-2J4C-FFCH-9F23

Vulnerability from github – Published: 2026-10-08 16:31 – Updated: 2026-10-08 16:31
VLAI
Summary
Excelize Decrypt: unrecoverable panics on malformed OLE/CFB encrypted workbooks
Details

Summary

Any file whose first 8 bytes are the OLE compound-file signature (D0 CF 11 E0 A1 B1 1A E1) is routed by OpenFile/OpenReader/OpenBytes → openReaderAt → Decrypt. The version dispatch only guarantees len(EncryptionInfo) >= 4 before handing attacker-controlled EncryptionInfo/EncryptedPackage buffers to standardDecrypt/agileDecrypt, and no callee validates structure. Malformed but version-valid content therefore fails as an unrecovered runtime panic instead of an error, terminating the calling process.

Details

All panic classes below were execution-confirmed against pristine master (ecd99d761fe0, 2026-09-08). excelize.go:211-213 maps Decrypt errors to ErrWorkbookFileFormat, but panics bypass that path and kill the process.

# Malformed input Panic Site
1 standard, len(EncryptionInfo) 4–11 slice bounds [:12] crypt.go:238
2 standard, attacker-controlled headerSize uint32 slice bounds [12:12+headerSize] / fixed-offset header reads crypt.go:238-249
3 standard, verifier remainder < 72 (AES) / 60 (RC4) bytes slice bounds in standardEncryptionVerifier crypt.go:282-295
4 standard, header.KeySize = 0xFFFFFFFF slice bounds [:536870911] with capacity 48 crypt.go:321
5 standard, EncryptedPackage stream missing/short slice bounds [8:0] crypt.go:268
6 agile, len(EncryptionInfo) 4–7 slice bounds [8:4] crypt.go:407
7 agile, valid XML without <keyEncryptors> index out of range [0] with length 0 crypt.go:416, 433
8 agile, saltValue decoded length ≠ AES block cipher.NewCBCDecrypter: IV length must equal block size crypt.go:425 → 512
9 any, keyData blockSize="0" integer divide by zero crypt.go:539

Note the asymmetry pinpointing the missing constraint: the agile path already checks len(EncryptedPackage) >= 8 (crypt.go:520-523) but the standard path does not (#5). Existing tests only cover the error paths (short <4 bytes → ErrUnknownEncryptMechanism, bad XML, base64 errors), never these panic paths.

PoC

Standalone programs (public API only, inputs built in memory) were provided to the maintainer by email: 1-decrypt-panic builds seven malformed CFB containers and shows each panic escaping the public Decrypt API plus one end-to-end OpenReader crash. All cases print PANIC on master and BLOCKED with the proposed patch. A regression guard proves legitimate decryption is unaffected: a workbook encrypted with the package's own Encrypt() still opens through the same code path.

(A separate advisory covers the unbounded/negative allocation in extractPart.)

Impact

Any service that calls OpenFile/OpenReader/OpenBytes on untrusted input (upload processing, mail scanning, spreadsheet conversion) can be killed remotely and without authentication by a file of ~100 bytes to ~3 KB. No password is required — panics occur during structural/parameter handling before successful decryption. Site variety means filtering one pattern does not help.

Proposed fix

A recover() boundary in Decrypt mapping any panic to ErrWorkbookFileFormat (restores the documented error-routing contract; legitimate standard/agile decryption unaffected). A complete patch has been provided to the maintainer; per-site length validation is recommended as defense in depth.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/xuri/excelize/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.3.1"
            },
            {
              "fixed": "2.11.1-0.20260915055537-22f76f9acb94"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-107214"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-248"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-08T16:31:32Z",
    "nvd_published_at": "2026-10-07T18:17:19Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nAny file whose first 8 bytes are the OLE compound-file signature (`D0 CF 11 E0 A1 B1 1A E1`) is routed by `OpenFile`/`OpenReader`/`OpenBytes` \u2192 `openReaderAt` \u2192 `Decrypt`. The version dispatch only guarantees `len(EncryptionInfo) \u003e= 4` before handing attacker-controlled `EncryptionInfo`/`EncryptedPackage` buffers to `standardDecrypt`/`agileDecrypt`, and no callee validates structure. Malformed but version-valid content therefore fails as an **unrecovered runtime panic** instead of an error, terminating the calling process.\n\n### Details\n\nAll panic classes below were execution-confirmed against pristine master (`ecd99d761fe0`, 2026-09-08). `excelize.go:211-213` maps `Decrypt` *errors* to `ErrWorkbookFileFormat`, but panics bypass that path and kill the process.\n\n| # | Malformed input | Panic | Site |\n|---|---|---|---|\n| 1 | standard, `len(EncryptionInfo)` 4\u201311 | slice bounds `[:12]` | `crypt.go:238` |\n| 2 | standard, attacker-controlled `headerSize` uint32 | slice bounds `[12:12+headerSize]` / fixed-offset header reads | `crypt.go:238-249` |\n| 3 | standard, verifier remainder \u003c 72 (AES) / 60 (RC4) bytes | slice bounds in `standardEncryptionVerifier` | `crypt.go:282-295` |\n| 4 | standard, `header.KeySize` = 0xFFFFFFFF | slice bounds `[:536870911]` with capacity 48 | `crypt.go:321` |\n| 5 | standard, `EncryptedPackage` stream missing/short | slice bounds `[8:0]` | `crypt.go:268` |\n| 6 | agile, `len(EncryptionInfo)` 4\u20137 | slice bounds `[8:4]` | `crypt.go:407` |\n| 7 | agile, valid XML without `\u003ckeyEncryptors\u003e` | index out of range `[0]` with length 0 | `crypt.go:416`, `433` |\n| 8 | agile, `saltValue` decoded length \u2260 AES block | `cipher.NewCBCDecrypter: IV length must equal block size` | `crypt.go:425` \u2192 `512` |\n| 9 | any, `keyData blockSize=\"0\"` | integer divide by zero | `crypt.go:539` |\n\nNote the asymmetry pinpointing the missing constraint: the agile path already checks `len(EncryptedPackage) \u003e= 8` (`crypt.go:520-523`) but the standard path does not (#5). Existing tests only cover the error paths (short `\u003c4` bytes \u2192 `ErrUnknownEncryptMechanism`, bad XML, base64 errors), never these panic paths.\n\n### PoC\n\nStandalone programs (public API only, inputs built in memory) were provided to the maintainer by email: `1-decrypt-panic` builds seven malformed CFB containers and shows each panic escaping the public `Decrypt` API plus one end-to-end `OpenReader` crash. All cases print PANIC on master and BLOCKED with the proposed patch. A regression guard proves legitimate decryption is unaffected: a workbook encrypted with the package\u0027s own `Encrypt()` still opens through the same code path.\n\n(A separate advisory covers the unbounded/negative allocation in `extractPart`.)\n\n### Impact\n\nAny service that calls `OpenFile`/`OpenReader`/`OpenBytes` on untrusted input (upload processing, mail scanning, spreadsheet conversion) can be killed remotely and without authentication by a file of ~100 bytes to ~3 KB. No password is required \u2014 panics occur during structural/parameter handling before successful decryption. Site variety means filtering one pattern does not help.\n\n### Proposed fix\n\nA `recover()` boundary in `Decrypt` mapping any panic to `ErrWorkbookFileFormat` (restores the documented error-routing contract; legitimate standard/agile decryption unaffected). A complete patch has been provided to the maintainer; per-site length validation is recommended as defense in depth.",
  "id": "GHSA-2j4c-ffch-9f23",
  "modified": "2026-10-08T16:31:32Z",
  "published": "2026-10-08T16:31:32Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/qax-os/excelize/security/advisories/GHSA-2j4c-ffch-9f23"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-107214"
    },
    {
      "type": "WEB",
      "url": "https://github.com/qax-os/excelize/pull/2395"
    },
    {
      "type": "WEB",
      "url": "https://github.com/qax-os/excelize/commit/22f76f9acb94b85b3eb9c4365ab4f750cebbc565"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/qax-os/excelize"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Excelize Decrypt: unrecoverable panics on malformed OLE/CFB encrypted workbooks"
}

No mitigation information available for this CWE.

No CAPEC attack patterns related to this CWE.