CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-115921

CVE-2026-115921: Null Pointer Dereference and Integer Conversion in ONNX ScanInferenceFunction

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 29, 2026·9 min read·3 visits

Executive Summary (TL;DR)

Unvalidated retrieval and unchecked unsigned casting of the 'num_scan_inputs' attribute in ONNX Scan shape inference routines allow untrusted models to crash the host application via null pointer dereference (CWE-476) or oversized memory allocation exceptions (CWE-195), bypassing pre-inference model validation.

Open Neural Network Exchange (ONNX) versions 1.4.0 prior to 1.22.0 contain a null pointer dereference (CWE-476) and a signed-to-unsigned integer conversion error (CWE-195) in the shape inference functions for the Scan operator. When processing an untrusted ONNX model, the functions ScanInferenceFunction, ScanInferenceFunction_opset8, and ScanInferenceFunction_opset9 fail to validate the presence and value of the required num_scan_inputs attribute. Omitting the attribute results in a direct null pointer dereference that crashes the host process via SIGSEGV, while supplying a negative value triggers an integer wrap-around during type narrowing that leads to an unhandled allocation failure. Notably, models containing a negative num_scan_inputs value bypass standard validation via onnx.checker.check_model().

Vulnerability Overview

Open Neural Network Exchange (ONNX) provides an open standard format and C++ library (with Python bindings) for representing machine learning models across frameworks. A core component of the ONNX library is its shape inference engine (onnx::shape_inference), which statically analyzes computation graphs to determine the tensor dimensions and data types of intermediate and output nodes before model execution or compilation.

In ONNX versions >= 1.4.0 and < 1.22.0, the shape inference routines responsible for handling the Scan control-flow operator fail to safely retrieve and validate the num_scan_inputs operator attribute. Specifically, the vulnerability affects ScanInferenceFunction in onnx/defs/controlflow/utils.cc, as well as the legacy operator set handlers ScanInferenceFunction_opset8 and ScanInferenceFunction_opset9 in onnx/defs/controlflow/old.cc.

This implementation flaw manifests as two distinct weakness classes depending on how an untrusted ONNX model is constructed: a NULL Pointer Dereference (CWE-476) when num_scan_inputs is omitted from the node definition, and a Signed to Unsigned Conversion Error (CWE-195) when num_scan_inputs is populated with a negative integer. Both conditions allow a crafted ONNX model file to terminate the process executing shape inference.

The attack surface encompasses any machine learning pipeline, model registry, compilation backend, or inference server that ingests external ONNX models and invokes onnx.shape_inference.infer_shapes(). Because a model with a negative num_scan_inputs value passes structural verification via onnx.checker.check_model(), standard pre-processing validation gates do not prevent the denial-of-service condition.

Root Cause Analysis

The ONNX operator specification for Scan defines num_scan_inputs as a required integer attribute that indicates the number of scan input tensors passed to the loop body subgraph. Within the C++ shape inference engine, operator attributes are stored in Protocol Buffer (AttributeProto) structures and accessed via the InferenceContext::getAttribute(const std::string& name) method, which returns a raw pointer (const AttributeProto*).

When a Scan node in a serialized model omits the num_scan_inputs attribute, ctx.getAttribute("num_scan_inputs") returns nullptr. In all three affected inference functions (ScanInferenceFunction, ScanInferenceFunction_opset8, and ScanInferenceFunction_opset9), the code immediately dereferenced this return value via ->i() without verifying that the pointer was non-null or that the attribute contained an integer field (has_i()). Executing this code path triggers an immediate segmentation fault (SIGSEGV) at the C++ layer, terminating the host interpreter or native binary.

The second failure mode stems from how the retrieved 64-bit signed protobuf integer (int64_t) is converted into an unsigned size_t variable. Prior to version 1.22.0, the codebase relied on a helper template named narrow_cast<T> defined in onnx/defs/shape_inference.h. Despite its name, narrow_cast<T> performed an unconditional static_cast<T> marked noexcept, performing no runtime bounds checking or sign validation.

> [!NOTE] > In the ONNX Protocol Buffer schema (onnx.proto), all single integer attributes (AttributeProto::i) are stored as signed 64-bit integers (int64). Consequently, schema validation alone cannot restrict an attribute to non-negative values unless explicit semantic checks are implemented in the operator's verification or inference routines.

When a model specifies a negative integer such as -1 for num_scan_inputs, narrow_cast<size_t>(-1) wraps the signed value to 18446744073709551615 (SIZE_MAX on 64-bit platforms). The inference functions then compute the number of loop-state variables using unsigned arithmetic (auto num_loop_state_vars = num_inputs - num_scan_inputs;). Because num_scan_inputs has wrapped to a massive unsigned value, subsequent arithmetic and vector sizing operations attempt to allocate or index out-of-bounds memory capacities, throwing an unhandled std::length_error or std::bad_alloc exception that aborts normal execution.

Code Analysis

The vulnerability resided across onnx/defs/controlflow/old.cc, onnx/defs/controlflow/utils.cc, and the header onnx/defs/shape_inference.h. In the vulnerable versions, attribute retrieval and type casting were combined into a single unchecked expression:

// Vulnerable pattern in ScanInferenceFunction (utils.cc) and opset8/opset9 (old.cc)
void ScanInferenceFunction(InferenceContext& ctx) {
  auto num_inputs = ctx.getNumInputs();
  // BUG 1: ctx.getAttribute() returns nullptr if 'num_scan_inputs' is missing -> SIGSEGV on ->i()
  // BUG 2: narrow_cast<size_t> performs an unchecked static_cast, wrapping negative int64_t values
  auto num_scan_inputs = narrow_cast<size_t>(ctx.getAttribute("num_scan_inputs")->i());
  auto num_loop_state_vars = num_inputs - num_scan_inputs;
  auto num_outputs = ctx.getNumOutputs();
  auto num_scan_outputs = num_outputs - num_loop_state_vars;
  // ...
}

In onnx/defs/shape_inference.h, the underlying narrow_cast utility was implemented as a wrapper around static_cast without value verification:

// Vulnerable implementation in onnx/defs/shape_inference.h
template <class T, class U>
static constexpr T narrow_cast(U&& u) noexcept {
  return static_cast<T>(std::forward<U>(u));
}

Commit dd6bc92ea39fd2274fd671f0734b0b8b558356f5 (merged via PR #7916) resolves both flaws by introducing safe attribute accessors and replacing narrow_cast with a checked narrow<T> template in onnx/defs/shape_inference.h:

// Patched implementation in onnx/defs/shape_inference.h
inline const AttributeProto& getRequiredAttribute(const InferenceContext& ctx, const std::string& name) {
  const auto* attr = ctx.getAttribute(name);
  if (attr == nullptr) {
    // Raises ONNX InferenceError instead of dereferencing a null pointer
    fail_shape_inference("Required attribute '", name, "' is missing");
  }
  return *attr;
}
 
inline int64_t getRequiredAttributeInt(const InferenceContext& ctx, const std::string& name) {
  const auto& attr = getRequiredAttribute(ctx, name);
  if (!attr.has_i()) {
    // Ensures the attribute is actually populated as an integer type
    fail_shape_inference("Required attribute '", name, "' must be an integer");
  }
  return attr.i();
}
 
template <class T, class U>
static constexpr T narrow(U&& u) {
  const U original = u;
  const T result = static_cast<T>(std::forward<U>(u));
  // Detects truncation (value mismatch) and sign changes across signed/unsigned boundaries
  if (static_cast<U>(result) != original || ((result < T{}) != (original < U{}))) {
    fail_shape_inference("narrow: value ", original, " cannot be represented in target type");
  }
  return result;
}

All three Scan inference functions were updated to use narrow<size_t>(getRequiredAttributeInt(ctx, "num_scan_inputs")). Regarding fix completeness, returning const AttributeProto& by reference in getRequiredAttribute prevents callers from skipping the null check, and replacing narrow_cast with narrow across the header ensures that any other callers inside shape_inference.h also gain protection against lossy or sign-changing integer conversions. However, note that downstream arithmetic (auto num_loop_state_vars = num_inputs - num_scan_inputs;) still operates on size_t values; if num_scan_inputs is positive but exceeds num_inputs, unsigned underflow in num_loop_state_vars remains a separate logical boundary to verify.

Exploitation

Exploiting CVE-2026-115921 requires no special privileges or complex memory layout manipulation. An attacker only needs to supply a crafted ONNX model (either as a binary .onnx protobuf file or via the ONNX text representation parser) to an application that runs onnx.shape_inference.infer_shapes().

Two distinct attack vectors exist. In the first vector, the attacker constructs a graph containing a Scan operator node with a valid body subgraph (body attribute) but omits the num_scan_inputs attribute entirely. When the target application invokes shape inference, the C++ backend attempts to read memory at offset 0x0 (plus the struct offset of AttributeProto::i_), immediately crashing the process with SIGSEGV.

In the second vector, the attacker includes num_scan_inputs = -1 in the Scan node attributes. Because the attribute is present and conforms to the int64 type required by AttributeProto, this model passes structural checks when the victim application runs onnx.checker.check_model(model). Once the validated model reaches onnx.shape_inference.infer_shapes(model), the -1 value wraps to SIZE_MAX, causing an uncaught exception or allocation crash.

import onnx
 
# Regression PoC from onnx/test/shape_inference_test.py
def reproduce_cve_2026_115921():
    scan_body = (
        "body = b (float[1] si, float[1] xi) => (float[1] so, float[1] xo) "
        "{ so = Identity(si) xo = Identity(xi) }"
    )
 
    # Vector 1: Missing 'num_scan_inputs' -> Triggers NULL pointer dereference (SIGSEGV)
    model_missing_attr = onnx.parser.parse_model(
        f"""
        <ir_version: 8, opset_import: [ "" : 9 ]>
        g (float[1] s, float[3,1] x) => (float[1] so, float[3,1] xo) {{
            so, xo = Scan <{scan_body}> (s, x)
        }}
        """
    )
 
    # Vector 2: Negative 'num_scan_inputs' (-1) -> Passes check_model(), fails in infer_shapes()
    model_negative_attr = onnx.parser.parse_model(
        f"""
        <ir_version: 8, opset_import: [ "" : 9 ]>
        g (float[1] s, float[3,1] x) => (float[1] so, float[3,1] xo) {{
            so, xo = Scan <num_scan_inputs = -1, {scan_body}> (s, x)
        }}
        """
    )
 
    for model in (model_missing_attr, model_negative_attr):
        try:
            onnx.shape_inference.infer_shapes(model, strict_mode=True)
        except onnx.shape_inference.InferenceError as err:
            print(f"Handled safely in >= 1.22.0: {err}")

Impact Assessment

The primary security impact of CVE-2026-115921 is an application-level Denial of Service (MITRE ATT&CK T1499: Endpoint Denial of Service). The vulnerability does not grant confidentiality disclosure (C:N) or arbitrary memory write primitives (I:N), as the null pointer dereference is strictly a read operation at a fixed near-null offset, and the integer conversion error leads to an immediate allocation failure rather than a controllable heap buffer overflow.

The CVSS v3.1 base score is 6.2 (Medium) with the vector CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. The Local attack vector (AV:L) reflects that the vulnerable library processes local model files or in-memory model structures, while User Interaction is marked None (UI:N) because automated MLOps pipelines, model conversion services, and inference servers routinely ingest and validate uploaded models without manual intervention.

In multi-tenant machine learning platforms or automated model evaluation services where Python worker processes call into the native onnx C++ extension, a SIGSEGV bypasses Python try...except blocks entirely. Consequently, a single malformed model submission terminates the entire worker process, disrupting concurrent tasks sharing that execution environment.

Threat intelligence metrics indicate a low likelihood of widespread wild exploitation. The Exploit Prediction Scoring System (EPSS) assigns CVE-2026-115921 a score of 0.00131 (0.131%, ~2.68th percentile), and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog.

Remediation

The definitive remediation is to upgrade the onnx package to version 1.22.0 or later, which includes commit dd6bc92ea39fd2274fd671f0734b0b8b558356f5. In version 1.22.0, both missing and negative num_scan_inputs attributes are caught during shape inference and converted into catchable onnx.shape_inference.InferenceError exceptions.

pip install --upgrade "onnx>=1.22.0"

For environments maintaining custom C++ builds of ONNX from source that cannot immediately rebase onto v1.22.0, cherry-picking commit dd6bc92ea39fd2274fd671f0734b0b8b558356f5 and 2bb50465112feca9003e1ed654d77f01ff1415ca resolves the vulnerability across onnx/defs/shape_inference.h, onnx/defs/controlflow/old.cc, and onnx/defs/controlflow/utils.cc.

> [!IMPORTANT] > Do not rely solely on onnx.checker.check_model() to filter untrusted models prior to shape inference on unpatched versions (< 1.22.0), as models with negative num_scan_inputs values pass the model checker.

If an immediate upgrade is not feasible in an environment that processes untrusted models, implement a pre-inference graph inspection step in Python before calling onnx.shape_inference.infer_shapes(). Iterate over all nodes in model.graph.node (and any nested subgraphs), locate nodes where op_type == "Scan", and verify that an attribute named num_scan_inputs exists, has type == onnx.AttributeProto.INT, and has an integer value strictly greater than 0 and less than or equal to the node's input count. Additionally, execute shape inference of untrusted models within isolated, ephemeral subprocesses or containers so that a native crash does not terminate the parent service.

Official Patches

ONNXGitHub Security Advisory GHSA-m4pr-6v3c-6fgr
ONNXPull Request #7916 implementing checked narrowing and required attribute validation
ONNXONNX v1.22.0 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
6.2/ 10
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.13%
Top 97% most exploited

Affected Systems

Open Neural Network Exchange (onnx)

Affected Versions Detail

Product
Affected Versions
Fixed Version
onnx
onnx
>= 1.4.0, < 1.22.01.22.0
AttributeDetail
CVE / GHSA IDCVE-2026-115921 / GHSA-m4pr-6v3c-6fgr
Weakness ClassCWE-476 (NULL Pointer Dereference) & CWE-195 (Signed to Unsigned Conversion Error)
Affected VersionsONNX >= 1.4.0, < 1.22.0 (Patched in 1.22.0)
Attack VectorLocal (AV:L) via untrusted ONNX model ingestion
CVSS v3.1 Score6.2 Medium (CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
EPSS Score0.131% (2.68th Percentile)
ImpactProcess Crash / Denial of Service (SIGSEGV or unhandled allocation exception)
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-476
NULL Pointer Dereference

The software dereferences a pointer that it expects to be valid, but is NULL, alongside a Signed to Unsigned Conversion Error (CWE-195) where a negative signed primitive is cast to a large unsigned value.

Known Exploits & Detection

GitHubOfficial regression test (test_scan_invalid_num_scan_inputs) demonstrating both the missing attribute (CWE-476) and negative attribute (CWE-195) crash vectors.

Vulnerability Timeline

Fix commit dd6bc92ea39fd2274fd671f0734b0b8b558356f5 merged via Pull Request #7916.
2026-05-07
GitHub Security Advisory GHSA-m4pr-6v3c-6fgr and CVE-2026-115921 published; NVD record created.
2026-10-26
Open Source Vulnerabilities (OSV) database record synchronized.
2026-10-28
EPSS score calculated and recorded.
2026-10-29

References & Sources

  • [1]GitHub Security Advisory GHSA-m4pr-6v3c-6fgr
  • [2]ONNX Fix Commit dd6bc92ea39fd2274fd671f0734b0b8b558356f5
  • [3]ONNX Pull Request #7916
  • [4]ONNX Release v1.22.0
  • [5]National Vulnerability Database (NVD) - CVE-2026-115921
  • [6]CVE.org Record - CVE-2026-115921
  • [7]OSV Database Entry - GHSA-m4pr-6v3c-6fgr

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•26 minutes ago•CVE-2026-118664
8.2

CVE-2026-118664: Quadratic Complexity Denial of Service in decode-uri-component

An inefficient algorithmic complexity vulnerability exists in the npm package decode-uri-component prior to version 0.5.1. When processing malformed URI strings containing invalid percent-escape sequences, the library falls back to a custom decoder that collects distinct percent-encoded runs into a dictionary and executes a full-string regular expression replacement for each entry. Supplying a payload with thousands of distinct percent-encoded sequences alongside a malformed escape triggers quadratic O(K * L) execution time, starving the single-threaded Node.js event loop and resulting in an unauthenticated Denial of Service.

Amit Schendel
Amit Schendel
1 views•9 min read
•about 2 hours ago•CVE-2026-91403
9.1

CVE-2026-91403: Cryptographic Trust Validation Bypass in Oracle Java SE JSSE via Compromised eMudhra Intermediate CAs

CVE-2026-91403 is a critical cryptographic trust validation flaw (CWE-327) in the Java Secure Socket Extension (JSSE) component of Oracle Java SE, Oracle GraalVM, and OpenJDK builds. Triggered by the compromise of private signing keys for eight intermediate Certificate Authorities operated by eMudhra (emSign), unpatched Java runtime environments implicitly trust fraudulent TLS and code-signing certificates issued by these compromised intermediates. Because Java disables online certificate revocation checking (OCSP/CRL) by default, an unauthenticated network attacker in an Adversary-in-the-Middle (AiTM) position can intercept, decrypt, and modify encrypted TLS communications or bypass code signature verification without triggering security exceptions.

Alon Barad
Alon Barad
5 views•12 min read
•about 2 hours ago•CVE-2026-115922
6.2

CVE-2026-115922: Denial of Service via Unchecked Expansion of Packed Sub-Byte Tensors in ONNX

Open Neural Network Exchange (ONNX) prior to version 1.22.0 contains a memory exhaustion vulnerability (CWE-789) in its Python tensor unpacking helpers and C++ model checker. Specifically, the _unpack_2bit() and _unpack_4bit() functions in onnx.numpy_helper unconditionally resize unpacked NumPy arrays to match attacker-controlled TensorProto.dims metadata without verifying that the underlying raw_data or int32_data buffers contain a corresponding number of packed bits. Furthermore, onnx.checker.check_tensor() previously bypassed length verification for sub-byte data types. Processing an untrusted ONNX model with packed sub-byte tensors (UINT2, INT2, UINT4, INT4, or FLOAT4E2M1) allows an unauthenticated attacker to trigger disproportionate memory allocations from minimal payloads, resulting in an out-of-memory (OOM) crash and denial of service.

Alon Barad
Alon Barad
6 views•10 min read
•about 3 hours ago•CVE-2026-115920
6.2

CVE-2026-115920: Out-of-Bounds Read in ONNX ConvTranspose Shape Inference

An out-of-bounds read vulnerability (CWE-125) exists in the Open Neural Network Exchange (ONNX) library across versions 1.2.1 prior to 1.22.0. The flaw occurs within the shape inference routines for the ConvTranspose operator when processing a model with a weight tensor rank less than three and an omitted kernel_shape attribute. Unchecked indexing into an empty vector triggers a memory segmentation fault, resulting in a Denial of Service (DoS) against applications inspecting or loading untrusted ONNX models.

Amit Schendel
Amit Schendel
4 views•10 min read
•about 4 hours ago•CVE-2026-115910
6.8

CVE-2026-115910: OpenID Connect Session-Binding Bypass and Account Takeover in Python Social Auth

A session-binding vulnerability in Python Social Auth (social-core) versions prior to 6.2.0 allows an attacker to perform authorization code injection against the OpenID Connect authentication backend. By storing generated OIDC nonces in a global database table without binding them to the initiating browser session, the library accepts any valid, unexpired nonce returned in an ID token regardless of which session originated the authentication transaction. When combined with the default disablement of Proof Key for Code Exchange (PKCE), an attacker who intercepts an unused authorization code can inject it into their own authentication flow to achieve full account takeover.

Amit Schendel
Amit Schendel
7 views•13 min read
•about 5 hours ago•CVE-2026-111497
9.8

CVE-2026-111497: Out-of-Bounds Heap Write and Remote Code Execution in Google Brotli Decoder (Node2Shell)

CVE-2026-111497, tracked in threat intelligence under the aliases Node2Shell, Broccoli2Shell, and HTTP2Shell, is a critical out-of-bounds heap write and denial-of-service vulnerability in the reference Google Brotli decompression library (c/dec/decode.c). The flaw originates from an unchecked return value and error-code conflation in DecodeBlockTypeAndLength() when processing malformed streams with single-block-type declarations (max_block_type <= 1). On the fast decoding path, the ignored error return causes the 32-bit unsigned block_length counter to underflow from 0 to UINT32_MAX (0xFFFFFFFF), corrupting internal decoder tables and enabling arbitrary heap memory overwrites via memmove16(). On the streaming path, the error return is misinterpreted as an incomplete bit-stream, trapping the worker process in an infinite 100% CPU loop. Because Google Brotli is embedded across major runtimes and infrastructure components—including Node.js, Envoy Proxy, Microsoft .NET, Istio, and Python—the vulnerability exposes a broad attack surface via standard HTTP Content-Encoding: br request and response bodies.

Amit Schendel
Amit Schendel
10 views•12 min read