Skip to content

Security: Disk encryption disableable via kernel cmdline, not measured in RTMR #618

Closed

Description

@kvinwang

Note: This issue documents a vulnerability that was originally reported privately as the repository security advisory GHSA-jwpv-vw5q-rj47 by @pbeza.

Root Cause

The kernel command line parameter dstack.storage_encrypted=false (controlled by the host operator) disables LUKS2 disk encryption for CVM persistent storage. The storage_encrypted state is NOT emitted as a runtime event and is NOT extended into RTMR3. Remote attestation verifiers cannot detect whether encryption has been disabled.

Attack Path

  1. Malicious host operator sets dstack.storage_encrypted=false in the VM kernel command line
  2. CVM boots without disk encryption — persistent storage is in plaintext
  3. Host operator can directly read CVM disk contents (keyshares, triples, presignatures, P2P keys)
  4. Remote attestation verification passes because RTMR3 does not include storage_encrypted state
  5. MPC verifier cannot distinguish between encrypted and unencrypted CVM deployments

Impact

Host operator can read all CVM persistent storage in plaintext without detection by remote attestation. For MPC nodes, this exposes keyshares, triples, presignatures, and P2P keys.

Suggested Fix

Emit storage_encrypted as a runtime event extended into RTMR3:

emit_runtime_event("storage-encrypted", storage_encrypted.to_string().as_bytes())?;

The MPC verifier should then check the RTMR3 event log for this event and reject CVMs where encryption is disabled.


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.

Activity

  1. kvinwang commented on Mar 27, 2026

    @kvinwang
    CollaboratorAuthor

    Maintainer response (copied from private security advisory GHSA-jwpv-vw5q-rj47):

    Thank you for the report!

    Here is our analysis:

    1. The kernel command line IS measured — in RTMR2, not RTMR3

    The advisory states that storage_encrypted is "NOT extended into RTMR3" and therefore not detectable by remote attestation. While it's true that there is no RTMR3 runtime event for storage_encrypted, the advisory overlooks that the entire kernel command line is measured into RTMR2 by the Linux EFI stub.

    In TDX, PCR 9 maps to RTMR[2]. The Linux EFI stub measures the full kernel cmdline (as UTF-16LE) into PCR 9 before the kernel proper starts executing. The dstack-mr tool pre-computes the expected RTMR2 value from the known cmdline:

    // dstack-mr/src/machine.rs
    let rtmr2_log = vec![
        kernel::measure_cmdline(self.kernel_cmdline),
        measure_sha384(&initrd_data),
    ];
    let rtmr2 = measure_log(&rtmr2_log);

    Adding dstack.storage_encrypted=false to the cmdline changes the cmdline string, which changes RTMR2, which changes mr_aggregated. A remote verifier comparing against expected measurements will detect this immediately.

    2. Standard deployments don't include storage_encrypted in the cmdline at all

    In the standard dstack image build (mkimage.sh), the kernel cmdline is:

    console=ttyS0 init=/init panic=1 ... dstack.rootfs_hash=<HASH> dstack.rootfs_size=<SIZE>
    

    There is no dstack.storage_encrypted parameter. The code in parse_dstack_options() defaults to storage_encrypted: true. The VMM constructs the QEMU command from metadata.json — there is no mechanism for an operator to inject extra cmdline args through the VMM API.

    If a host operator bypasses the VMM and manually modifies the QEMU -append argument, the changed cmdline is measured into RTMR2, making it detectable.

    Summary

    Claim Reality
    storage_encrypted not measured in RTMR Measured in RTMR2 as part of the kernel cmdline
    Verifiers cannot detect disabled encryption RTMR2 change is reflected for the changes
    Host operator can disable encryption silently Changing cmdline changes RTMR2; bypassing VMM also changes measurements
  2. added
    securitySecurity-related issue, report, or hardening work
    security: reportPublic security report or already-public security finding
    security: not-production-vulnDoes not compromise supported production deployments under the documented threat model
    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: not-production-vulnDoes not compromise supported production deployments under the documented threat modelsecurity: 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