Finding 2/2: The Case of the Inverted Check.
Vulnerability WriteupApril 22, 2026

Finding 2/2: The Case of the Inverted Check.

By Rahul Saxena (@saxenism)

Inverted PCESVN Comparator in Oasis Core's TCB Level Matching

Severity: Medium Affected components: TCBLevel.matches() in both Go (go/common/sgx/pcs/tcb.go) and Rust (runtime/src/common/sgx/pcs/tcb.rs) implementations of Intel DCAP TCB level matching Repository: github.com/oasisprotocol/oasis-core

Intel's DCAP verification tells you two things: whether a quote is authentic, and whether the platform that produced it is still running firmware Intel considers safe. That second question is answered by matching the platform's TCB components against Intel's published TCB levels. Oasis Core implemented one of those comparisons backwards. In the stale-platform direction, the bug failed open, so the most security-relevant case could remain silent.

This issue was identified by Bluethroat Labs and responsibly disclosed to the Oasis team in January 2026. The fix was included in Oasis Core 26.0.

Executive Summary

  • The TCBLevel.matches() function in both Go and Rust implementations of Oasis Core contained an inverted PCESVN comparison.
  • The bug rejected platforms with newer, patched PCE firmware while accepting platforms with older, outdated firmware.
  • Because the comparison was fail-open for stale platforms and fail-closed for updated ones, the bug could remain silent unless a newer-than-expected PCESVN was encountered.
  • Both the Go and Rust implementations contained the same inversion, suggesting shared implementation history.
  • The fix was a single-line change in each file, flipping the operand order.

Background

Intel DCAP (Data Center Attestation Primitives) quote verification includes a step called TCB level matching. Intel publishes a list of TCB levels, each describing a specific firmware configuration and its associated security status (e.g., UpToDate, OutOfDate, SWHardeningNeeded, Revoked).

During verification, the platform's firmware version numbers are compared against each TCB level in Intel's list. The matching algorithm is defined in Intel's API specification and works as follows:

  1. Compare each of the platform's SGX TCB component SVNs against the TCB level's values. If all platform values are greater than or equal to the TCB level's values, proceed.
  2. Compare the platform's PCESVN (Provisioning Certification Enclave Security Version Number) against the TCB level's PCESVN. If the platform value is greater than or equal, the level matches.
  3. For TDX, compare TEE TCB SVN values similarly.

The direction of comparison matters. Intel's spec says: "If [the platform PCESVN] is greater or equal to the value in TCB Level, read status assigned to this TCB level." In code, this means: reject if platform_pcesvn < tcb_level_pcesvn.

Vulnerability Details

The matches() function in both Go and Rust performed the PCESVN comparison backwards. Here is the buggy Go code:

// go/common/sgx/pcs/tcb.go -- TCBLevel.matches()

// SGX component SVN check (CORRECT direction):
for i, comp := range tl.TCB.SGXComponents {
    if sgxCompSvn[i] < comp.SVN {  // platform < requirement → reject ✓
        return false
    }
}

// PCESVN check (INVERTED):
if tl.TCB.PCESVN < pcesvn {  // requirement < platform → reject ✗
    return false
}

And the equivalent buggy Rust code:

// runtime/src/common/sgx/pcs/tcb.rs -- TCBLevel::matches()

// SGX component SVN check (CORRECT direction):
for (i, comp) in self.tcb.sgx_components.iter().enumerate() {
    if sgx_comp_svn[i] < comp.svn {  // platform < requirement → reject ✓
        return false;
    }
}

// PCESVN check (INVERTED):
if self.tcb.pcesvn < pcesvn {  // requirement < platform → reject ✗
    return false;
}

The SGX component SVN checks use the correct direction: platform < requirement → reject. The PCESVN check directly below them flips it: requirement < platform → reject. There is no coherent design rationale where "higher component SVN is acceptable" but "higher PCESVN is rejected." The same inversion appears in both Go and Rust, strongly suggesting shared implementation history rather than two unrelated design choices.

What the Bug Actually Did

Given a TCB level that requires PCESVN = 10:

Platform PCESVNExpected ResultActual (Buggy) Result
9 (outdated firmware)Reject -- does not meet requirementAccept (false positive)
10 (exact match)AcceptAccept
12 (newer firmware)Accept -- exceeds requirementReject (false negative)

The bug had two effects running simultaneously:

Fail-open for stale platforms. A platform running outdated PCE firmware could match a TCB level that required a higher version. This meant the platform could silently receive a better TCB status than Intel intended. An OutOfDate platform could be classified as SWHardeningNeeded or even UpToDate, depending on the ordering of TCB levels in Intel's collateral.

Fail-closed for patched platforms. A platform running newer PCE firmware than the TCB level required would be rejected from matching that level. This could cause correctly updated platforms to fall through to a worse TCB level or fail matching entirely.

Why It Stayed Hidden

This class of bug is difficult to catch because one side of the comparison fails open while the other fails closed.

For exact matches, the bug produces the correct result. For lower platform PCESVN values, the bug can incorrectly accept without producing an explicit error. The more visible symptom is the opposite case: a newer platform failing to match as expected.

That makes the bug easy to miss in routine testing unless cases with lower, equal, and higher PCESVN values are exercised explicitly.

The Oasis team confirmed this after review: "We were fortunate that, in practice, there was no unmatching PCESVN case yet (for the same TCB levels), so the issue has not manifested on our live networks so far."

What Could Have Gone Wrong (But Did Not)

No exploitation of this vulnerability was observed during the assessment. The following scenarios describe damage that was possible given the code as written, not damage that occurred.

Silent TCB status upgrade. If Intel published a security advisory that downgraded a specific PCE version, a platform still running that version could continue matching against a higher TCB level. The platform would appear to have acceptable security posture when Intel had already flagged it. Any downstream trust decision based on TCB status would inherit the incorrect assessment.

Attestation failure for compliant platforms. In the opposite direction, a validator or ROFL application running a genuinely updated platform could fail TCB level matching and receive a degraded status. Depending on policy configuration, this could prevent registration or trigger unnecessary alerts.

What This Did Not Allow

The bug did not allow forging attestation quotes. It did not bypass cryptographic verification of the quote itself. It did not allow arbitrary code execution or direct access to enclave secrets. The vulnerability was confined to the TCB level matching step, meaning it affected which security status label a genuine platform received, not whether the platform was genuine.

Why We Classify This as Medium

The impact class is meaningful: a fail-open comparator in attestation verification that silently upgrades the trust status of outdated platforms is a real security gap. It sits on the path that determines whether a platform's firmware meets Intel's current security requirements.

The reason this is Medium rather than High is reachability. The observable effect depends on the specific ordering and PCESVN values in Intel's published TCB levels at any given time. The Oasis team confirmed that no PCESVN mismatch had occurred on their live networks during the period the bug was present. The bug was real, but the triggering collateral condition had not yet occurred on their observed live networks.

We originally submitted this as High. After review and discussion with the Oasis team, the final classification was Medium, which we accepted.

Fix

The fix was a one-line change in each implementation, flipping the operand order to match the Intel specification:

Go:

// Before (buggy):
if tl.TCB.PCESVN < pcesvn {

// After (fixed):
if pcesvn < tl.TCB.PCESVN {

Rust:

// Before (buggy):
if self.tcb.pcesvn < pcesvn {

// After (fixed):
if pcesvn < self.tcb.pcesvn {

The fix also added comprehensive test cases covering higher, lower, and equal PCESVN values to prevent regression.

Disclosure Timeline

January 7, 2026. We initiated contact with the Oasis team and submitted our first PGP-encrypted security report concerning Oasis ROFL. The team acknowledged receipt the same day.

January 8 to January 13, 2026. Over the following week, we submitted additional encrypted reports as our review expanded. By January 13, Oasis confirmed receipt of eight reports and began a consolidated review.

January 26, 2026. Oasis sent its first consolidated technical response, addressing the reported issues one by one.

January 27 to January 30, 2026. During our review, we noticed this finding had not been addressed in the consolidated response. We reattached it and followed up.

February 3, 2026. Oasis confirmed the finding was valid and increased total compensation by $1,000.

February 17 to February 27, 2026. Back-and-forth on severity classification. We argued this warranted High given the fail-open nature and dual-implementation scope. Oasis maintained that real-world exploitability depended on specific collateral configurations.

March 2, 2026. Oasis issued final classification: Medium.

March 3, 2026. We accepted the classification and moved to closure.

March 5, 2026. Oasis confirmed no nondisclosure obligations and requested coordinated timing until Oasis Core 26.0 was live on mainnet. Public discussion was welcome after rollout, with attribution to Bluethroat Labs.

March 16, 2026. Bounty payment confirmed received.

Key Takeaway

When implementing comparison-based matching against a specification, the direction of every comparator matters. This bug was easy to write, hard to catch, and invisible in production because it was fail-open. The SGX component SVN comparisons three lines above were correct. The PCESVN comparison directly below them was not. The internal inconsistency was the clearest signal that something was wrong, but in a function where every comparison looks structurally similar, a flipped operand does not stand out during review.

If you implement DCAP TCB level matching, test with platform values that are strictly greater than, equal to, and strictly less than the TCB level requirements. All three cases must be covered because two of them produce correct results even with an inverted comparator.

References

This vulnerability was discovered by Rahul Saxena of Bluethroat Labs during a security assessment of the Oasis ROFL and attestation verification surface. Responsible disclosure was coordinated with the Oasis team.

© 2026 Bluethroat Labs