Skip to content

[security] RatchetCache retains old channel keys in memory without explicit eviction #178

@intendednull

Description

@intendednull

Problem

crates/crypto/src/lib.rs:483-599 implements RatchetCache, which stores derived ChannelKey values in a BTreeMap. While ChannelKey derives ZeroizeOnDrop, the cache has no method to explicitly wipe all keys when a user leaves a channel or server.

pub struct RatchetCache {
    ratchets: BTreeMap<u32, KeyRatchet>,
    cache: BTreeMap<(u32, u64), ChannelKey>,
    max_entries: usize,
}

Old keys accumulate in memory until eviction pressure (cache full → oldest entry removed) or the cache is dropped. In a long-lived session with active channels, hundreds of old message keys may reside in WASM linear memory.

Severity

MEDIUM — information disclosure risk. A process with memory access (core dump, malicious browser extension reading WASM memory, Spectre-class side channels) could extract previously-derived keys, allowing decryption of old messages.

Fix

Add an explicit clear() method and call it on channel leave:

impl RatchetCache {
    /// Wipe all cached keys and ratchets. Call on channel leave / server exit.
    pub fn clear(&mut self) {
        self.cache.clear();
        self.ratchets.clear();
    }
}

The existing evict_epoch() method (line 585) provides per-epoch cleanup but must be called explicitly. Wire it into the client's channel-leave / server-disconnect flow.

Locations

  • crates/crypto/src/lib.rs:483-599 — RatchetCache struct
  • crates/crypto/src/lib.rs:585 — evict_epoch (exists but not called on leave)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions