{
  "affected": [
    {
      "ranges": [
        {
          "database_specific": {
            "extracted_events": [
              {
                "introduced": "0"
              },
              {
                "fixed": "1.0.0-beta.19"
              }
            ],
            "source": [
              "AFFECTED_FIELD",
              "REFERENCES"
            ]
          },
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "74d6be658e1ad252f87943292ba09bdd4da80bd4"
            }
          ],
          "repo": "https://github.com/noir-lang/noir",
          "type": "GIT"
        }
      ]
    }
  ],
  "aliases": [
    "GHSA-jj7c-x25r-r8r3"
  ],
  "database_specific": {
    "cna_assigner": "GitHub_M",
    "cwe_ids": [
      "CWE-131"
    ],
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41197.json"
  },
  "details": "Noir is a Domain Specific Language for SNARK proving systems that is designed to use any ACIR compatible proving system, and Brillig is the bytecode ACIR uses for non-determinism. Noir programs can invoke external functions through foreign calls. When compiling to Brillig bytecode, the SSA instructions are processed block-by-block in `BrilligBlock::compile_block()`. When the compiler encounters an `Instruction::Call` with a `Value::ForeignFunction` target, it invokes `codegen_call()` in `brillig_call/code_gen_call.rs`, which dispatches to `convert_ssa_foreign_call()`. Before emitting the foreign call opcode, the compiler must pre-allocate memory for any array results the call will return. This happens through `allocate_external_call_results()`, which iterates over the result types. For `Type::Array` results, it delegates to `allocate_foreign_call_result_array()` to recursively allocate memory on the heap for nested arrays. The `BrilligArray` struct is the internal representation of a Noir array in Brillig IR. Its `size` field represents the semi-flattened size, the total number of memory slots the array occupies, accounting for the fact that composite types like tuples consume multiple slots per element. This size is computed by `compute_array_length()` in `brillig_block_variables.rs`. For the outer array, `allocate_external_call_results()` correctly uses `define_variable()`, which internally calls `allocate_value_with_type()`. This function applies the formula above, producing the correct semi-flattened size. However, for nested arrays, `allocate_foreign_call_result_array()` contains a bug. The pattern `Type::Array(_, nested_size)` discards the inner types with `_` and uses only `nested_size`, the semantic length of the nested array (the number of logical elements), not the semi-flattened size. For simple element types this works correctly, but for composite element types it under-allocates. Foreign calls returning nested arrays of tuples or other composite types corrupt the Brillig VM heap. Version 1.0.0-beta.19 fixes this issue.",
  "id": "CVE-2026-41197",
  "modified": "2026-07-08T05:39:21.669117121Z",
  "published": "2026-04-23T00:35:37.842Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/noir-lang/noir/releases/tag/v1.0.0-beta.19"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41197.json"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/noir-lang/noir/security/advisories/GHSA-jj7c-x25r-r8r3"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41197"
    }
  ],
  "schema_version": "1.7.5",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Brillig: Heap corruption in foreign call results with nested tuple arrays"
}