Skip to content

TCB component-wise comparison silently truncates via `.zip()`

Low
kvinwang published GHSA-6q6c-vvf9-fj3w Jul 22, 2026

Package

cargo dcap-qvl (Rust)

Affected versions

>= 0.3.9, < 0.4.1

Patched versions

>= 0.4.1
pip dcap-qvl (pip)
>= 0.3.9, < 0.4.1
>= 0.4.1

Description

Root Cause

Platform TCB matching uses Rust's .zip() iterator to compare cpu_svn bytes (16 bytes extracted from the PCK certificate) against sgx_components (deserialized from Intel's TCB Info JSON). The .zip() adapter stops at the shorter of the two iterators, silently skipping any remaining elements:

// src/verify.rs:509-516
let sgx_components: Vec<u8> = tcb_level.tcb.sgx_components.iter().map(|c| c.svn).collect();
if sgx_components.is_empty() {
    bail!("No SGX components in the TCB info");
}
// Component-wise comparison: every cpu_svn[i] must be >= sgx_components[i]
if cpu_svn.iter().zip(&sgx_components).any(|(a, b)| a < b) {
    continue;
}

The sgx_components field is deserialized as Vec<TcbComponents> (in tcb_info.rs:44-45) with no length validation — any number of components is accepted. The only guard is an is_empty() check, but there is no assertion that sgx_components.len() == cpu_svn.len() (i.e., 16).

The same pattern exists for TDX components at lines 530-534:

if td_report
    .tee_tcb_svn
    .iter()
    .zip(&tdx_components)
    .any(|(a, b)| a < b)
{
    continue;
}

Notably, the JavaScript port of this library (verify.js:445-448) correctly validates array length equality before comparison:

function compareSvnArrays(actual, required) {
    if (actual.length !== required.length) {
        return false;  // <-- explicit length check, absent in Rust
    }
    // ...
}

This confirms the issue was recognized as a concern in the JS implementation but missed in the Rust version.

Attack Path

  1. Attacker cannot directly modify Intel-signed TCB Info JSON. However, the library's correctness should not depend solely on Intel never making a mistake in collateral formatting.
  2. If Intel publishes TCB Info with fewer than 16 sgxtcbcomponents (e.g., during a format transition or version mismatch), SVN values at positions beyond the component count are never checked.
  3. A platform with outdated SVNs in those unchecked positions would incorrectly pass TCB matching and receive a better status than warranted.

Impact

If TCB Info contains fewer than 16 SGX components (or fewer TDX components than expected), CPU SVN / TEE TCB SVN values at positions beyond the component count are not validated. The library would accept a platform that should be classified at a lower TCB level. The TCB Info signature provides protection, but defense-in-depth requires the library to validate the invariant it depends on.

Suggested Fix

Add explicit length checks before the .zip() comparison:

if sgx_components.len() != cpu_svn.len() {
    bail!(
        "SGX component count mismatch: expected {}, got {}",
        cpu_svn.len(),
        sgx_components.len()
    );
}

And for TDX:

if tdx_components.len() != td_report.tee_tcb_svn.len() {
    bail!(
        "TDX component count mismatch: expected {}, got {}",
        td_report.tee_tcb_svn.len(),
        tdx_components.len()
    );
}

Note: This finding was reported automatically as part of an AI/Claude-driven internal audit by the NEAR One MPC team. It has not been manually verified by a human to confirm whether it constitutes an actual security issue.

Severity

Low

CVE ID

No known CVE

Weaknesses

Incorrect Calculation of Buffer Size

The product does not correctly calculate the size to be used when allocating a buffer, which could lead to a buffer overflow. Learn more on MITRE.

Credits