Skip to content

Unbounded allocation in VecOf decode #567

Closed

Description

@pbeza

The VecOf<T> SCALE decoder in dstack/ra-tls/src/attestation/mod.rs reads a length prefix from untrusted input and pre-allocates a Vec of that size without any upper bound, enabling an attacker to trigger arbitrarily large memory allocations with a crafted payload.

Root Cause

The VecOf decoder reads a count value from untrusted input and allocates a vector of that size without any upper bound:

// codecs.rs:24-37
let count = u32::decode(input)?;
let mut items = Vec::with_capacity(count as usize);  // Unbounded allocation
for _ in 0..count {
    items.push(T::decode(input)?);
}

A malformed event log entry with a large count value can trigger allocation of gigabytes of memory.

Attack Path

  1. Attacker crafts a malformed CCEL (CC Event Log) entry with count = 0xFFFFFFFF
  2. Application parses the event log using the VecOf decoder
  3. Vec::with_capacity(4294967295) attempts to allocate ~4 GB
  4. Process crashes due to OOM or the system becomes unresponsive

Impact

Denial of service when parsing malformed event logs. The event log could be corrupted by a malicious host (the CCEL table is provided by the firmware/VMM) or by a compromised process inside the CVM.

Suggested Fix

Add a maximum count limit:

const MAX_VEC_COUNT: u32 = 65536;  // Reasonable upper bound

let count = u32::decode(input)?;
if count > MAX_VEC_COUNT {
    return Err(Error::CountTooLarge(count));
}
let mut items = Vec::with_capacity(count as usize);

Note: This issue was created automatically. The vulnerability report was generated by Claude and has not been verified by a human.

Activity

  1. kvinwang commented on Mar 18, 2026

    @kvinwang
    Collaborator

    Fixed in #570. Added a const generic MAX_LEN with a default of 65536 to VecOf, so decode now rejects counts exceeding the limit. Also capped with_capacity to 1024 to prevent large pre-allocations from untrusted input.

    Existing VecOf<I, T> usages are unaffected due to the default value. Callers can override with e.g. VecOf<u32, u8, 1048576> if needed.

  2. h4x3rotab commented on Jun 30, 2026

    @h4x3rotab
    Contributor

    Maintainer triage update: this was fixed by #570 and is recorded in the public security report table: https://github.com/Dstack-TEE/dstack/blob/master/docs/security/public-security-reports.md#public-reports-and-findings

    Disposition: valid report, fixed. #570 caps VecOf decode length and pre-allocation.

    Closing as fixed.

  3. added
    securitySecurity-related issue, report, or hardening work
    security: reportPublic security report or already-public security finding
    security: fixedSecurity report addressed by a code or configuration change
    on Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity-related issue, report, or hardening worksecurity: fixedSecurity report addressed by a code or configuration changesecurity: reportPublic security report or already-public security finding

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions