Skip to content

cel: add bounds check in unmarshalFirstTLV to prevent OOM DoS#30

Open
adilburaksen wants to merge 1 commit intogoogle:mainfrom
adilburaksen:fix/cel-tlv-oom-dos
Open

cel: add bounds check in unmarshalFirstTLV to prevent OOM DoS#30
adilburaksen wants to merge 1 commit intogoogle:mainfrom
adilburaksen:fix/cel-tlv-oom-dos

Conversation

@adilburaksen
Copy link
Copy Markdown

Summary

unmarshalFirstTLV in cel/canonical_eventlog.go reads a uint32 value length
from the input buffer and passes it directly to make([]byte, valueLength) with no
bounds check. A crafted 5-byte TLV ([type][0xFF 0xFF 0xFF 0xFF]) causes a
4 GiB allocation attempt, crashing any process that parses untrusted CEL data.

Root cause

valueLength := binary.BigEndian.Uint32(lengthBytes)  // raw uint32, no check
// ...
valueBytes := make([]byte, valueLength)              // ← up to 4 GiB

Impact

Any caller of DecodeToCEL or unmarshalDigests that processes attacker-supplied
CEL bytes is vulnerable. Concretely, attestation verifiers that parse Confidential
VM event logs (e.g. go-tpm-tools server.VerifyAttestation) receive the event log
from the client VM — making this reachable from untrusted input.

Fix

Add maxTLVValueSize = 1<<20 (1 MiB) and reject oversized lengths before
allocating:

if valueLength > maxTLVValueSize {
    return TLV{}, fmt.Errorf("TLV value length %d exceeds maximum %d", valueLength, maxTLVValueSize)
}

The cap is generous: the fixed CEL fields (recnum = 8 B, regIndex = 1 B) and digest
TLVs (a few hundred bytes) are well below this limit. Even custom content events are
unlikely to approach 1 MiB in practice.

Test

TestOversizeTLVValueLength (added to cel/canonical_eventlog_test.go) crafts a
5-byte TLV with valueLength = maxTLVValueSize+1 and asserts that unmarshalFirstTLV
returns an error without performing a large allocation.

unmarshalFirstTLV reads a uint32 valueLength from the input buffer
and passes it directly to make([]byte, valueLength) without any
bounds check. A 5-byte crafted TLV with valueLength=0xFFFFFFFF
triggers a 4 GiB allocation attempt, causing an OOM condition in
any process that parses untrusted CEL data (e.g. attestation
verifiers reading a Confidential VM's event log).

Fix: add maxTLVValueSize = 1<<20 (1 MiB) and reject any TLV whose
declared length exceeds this limit before allocating.

Regression test: TestOversizeTLVValueLength
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant