Skip to content

SgxVerifier: enclave-identity (MRENCLAVE/MRSIGNER) check is opt-in and defaults OFF while registerInstance is permissionless #21761

@dantaik

Description

@dantaik

Summary

SgxVerifier.registerInstance() is permissionless and registers an attacker-supplied Ethereum address taken directly from the SGX quote's reportData. It trusts whatever IAttestation.verifyParsedQuote(...) returns. In AutomataDcapV3Attestation, the application-enclave identity check (MRENCLAVE / MRSIGNER — i.e. "is this quote actually from the Taiko prover program?") is only performed when checkLocalEnclaveReport == true, and that flag defaults to false (storage zero-init) with no toggleLocalReportCheck() call anywhere in script/ or deployments/.

This is filed for input/clarification from @smtmfft on the live trust model — I could not determine the on-chain value of the flag from the repo, and the evidence is contradictory (see below). If the flag is on in production, this is sound and the only ask is to make the invariant enforced rather than operator-dependent. If it is off, it is a live key-forgery path against the SGX leg.

Code references

  • contracts/layer1/verifiers/SgxVerifier.sol:113-124registerInstance() is external with no access control; registers address(bytes20(_attestation.localEnclaveReport.reportData)) after only require(verified, ...).
  • contracts/layer1/automata-attestation/AutomataDcapV3Attestation.sol:407-415 — MRENCLAVE/MRSIGNER are checked only inside if (checkLocalEnclaveReport) { ... }.
  • contracts/layer1/automata-attestation/AutomataDcapV3Attestation.sol:37bool public checkLocalEnclaveReport; (defaults false).
  • contracts/layer1/automata-attestation/AutomataDcapV3Attestation.sol:143-146toggleLocalReportCheck() is the only way to enable it; grep finds no call in script/ or deployments/.
  • contracts/layer1/verifiers/SgxVerifier.sol:182-188_isInstanceValid() (proof time) only checks the address matches the stored instance and the validity window. It never re-checks MRENCLAVE/MRSIGNER.

Why this matters

If checkLocalEnclaveReport is false on the live attestation contract(s), an attacker can:

  1. Run any SGX enclave (their own program, not raiko/gaiko) that signs a reportData containing an Ethereum key they control.
  2. Obtain a genuine Intel DCAP quote for it (it is a real enclave, just not the Taiko one).
  3. Call registerInstance(...) permissionlessly — it passes, because without the MRENCLAVE/MRSIGNER check, steps 3–8 only prove "this is a real Intel SGX quote with acceptable TCB", not "this is the Taiko prover".
  4. Sign arbitrary "SGX proofs" for any state transition with their key.

On mainnet's MainnetVerifier (SGX and ZK, 2-of-N) this defeats the SGX leg but not the ZK leg, so it is not instant fund loss. Under any 1-of-N AnyVerifier wiring it would be total compromise.

Important operational note: because _isInstanceValid never re-validates MRENCLAVE, flipping the flag on does not retroactively invalidate an instance already registered while it was off. Remediation (if the flag is currently off) would also require enumerating instances[0..nextInstanceId) and deleteInstances(...) for any key not attributable to a genuine raiko/gaiko enclave.

Questions / requests for @smtmfft

  1. Is checkLocalEnclaveReport == true on the live SGXRETH_ATTESTER / SGXGETH_ATTESTER attestation contracts today? (Governance proposals 0004/0009/0010 call setMrEnclave(...) to populate the trusted set, which only matters if the check is enabled — hence the contradiction with the default and the missing toggle.)
  2. If yes: is there appetite to enforce this as an invariant rather than rely on operator configuration? e.g. a deploy/governance-time assertion that the flag is set after SGX configuration, or moving the MRENCLAVE allowlist into SgxVerifier itself so SGX trust is self-contained rather than depending on an optional flag in the vendored Automata library.
  3. If no (flag is off): this should be treated as a live high-severity exposure — confirm and we can prioritize enabling the check + auditing/cleaning the existing instance set.

Suggested direction (pending clarification)

  • Operational: verify the live flag; if off, audit & prune registered instances, populate the trusted MRENCLAVE/MRSIGNER set, then enable the check.
  • Code: make "ship with the check off" fail loudly (init-time default true or a post-configuration assertion), so a zero-value default can never silently disable enclave-identity verification.

Found during a recursive audit of the core protocol contracts and their dependencies.

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions