Review by deepseek/deepseek-v4-pro
commit: 765b6710b621474e53c575a0ae3f02b76643355d
usage: {'prompt_tokens': 100787, 'completion_tokens': 22202, 'total_tokens': 122989, 'cost': 0.12631617, 'is_byok': False, 'prompt_tokens_details': {'cached_tokens': 0, 'cache_write_tokens': 0, 'audio_tokens': 0, 'video_tokens': 0}, 'cost_details': {'upstream_inference_cost': 0.12631617, 'upstream_inference_prompt_cost': 0.08768469, 'upstream_inference_completions_cost': 0.03863148}, 'completion_tokens_details': {'reasoning_tokens': 20191, 'image_tokens': 0, 'audio_tokens': 0}}
time: 543s
Critical: Operator can bypass the seven-day time‑lock by manipulating the host clock and blocking drand beacon updates.
- File / function:
crates/enclave/src/beacon.rs(lock_round_at_ms),crates/enclave/src/attest.rs(trusted_time_ms),crates/enclave/src/proxy.rs(start‑time acquisition). - Attacker: The operator who owns the parent EC2 instance.
- What they do: Set the parent system clock to a past date, block all outbound drand API hosts so the enclave never verifies a beacon, and then send requests.
- Why the code allows it: The lock calculation uses the Nitro attestation timestamp as the primary time source. The NSM timestamp is simply the host clock, fully controlled by the operator. The drand beacon is only a secondary lower bound (
max(trusted, beacon)); if no beacon has ever been fetched,verified_roundstays 0 and provides no bound. The operator can therefore make the trusted timestamp arbitrarily old, causing the lock round to be already published and allowing immediate decryption. - Suggested fix: Do not trust the host‑derived NSM timestamp for the lock. Require that a recent drand beacon (e.g., published within the last 60 seconds) has been fetched and verified before any request is accepted. Use only the beacon’s publication time (plus the required delay) to compute the unlock round. If the beacon is stale or unreachable, refuse all requests with 503 (fail‑closed). This anchors the lock to an external, non‑manipulatable clock.
Medium: Slow request bodies allow an attacker to exhaust in‑flight slots for up to an hour, causing denial of service.
- File / function:
crates/enclave/src/proxy.rs(forward_entry,TeeBody). - Attacker: Any sender.
- What they do: Open
max_in_flight(256) connections, send complete headers quickly, then stream request bodies at an extremely slow rate (e.g., one byte per minute). - Why the code allows it: There is a 15‑s header read timeout and a 3600‑s connection lifetime, but no timeout on the request body stream after headers are received. Each connection holds an in‑flight slot until the whole exchange finishes or the connection is killed, so 256 slow streams can block all proxy capacity for up to one hour.
- Suggested fix: Add a timeout on receiving the request body (e.g., close the exchange if no body data arrives for 60 seconds) or enforce a total request‑duration timeout significantly shorter than
max_connection_seconds.
Low: Potential panic via unwrap() on HTTP response builders.
- File / function:
crates/enclave/src/proxy.rs(functionstext,landing,attestation). - Attacker: Not directly exploitable today, but a latent robustness risk.
- Why the code allows it: Several
Response::builder().body(full(...)).unwrap()calls decode static strings, but a future dynamic header value (e.g., from a mis‑escaped host) could produce an invalid header value and panic the enclave process (panic=abort in release). - Suggested fix: Replace each
unwrap()with.expect("valid response")or proper error handling to guarantee a clean error instead of a crash.
Info / No higher‑severity findings (items reviewed without discovering a vulnerability):
- Confidentiality of proxied content before the lock period: Content is TLS‑terminated inside the enclave, encrypted with age+tlock before it leaves, and the parent sees only sealed ciphertext. No request‑derived data leaks through diagnostics, error messages, or vsock channels.
- Weakening sender verification: The attestation endpoint correctly binds the TLS key (SPKI) into the signed attestation document;
tlproxy verifychecks the signature chain, nonce, certificate match, and PCRs. A non‑enclave endpoint cannot produce a valid attestation document. - WireGuard/TCP stack correctness: The userspace WireGuard implementation appears free of panics or data corruption that would drop plaintext records (records are sealed before sending). The stack may fail closed under network interruption.
- Availability limits: All advertised limits (
max_connections,max_in_flight,max_body_bytes, capture budgets, queue capacities) are enforced.
Overall verdict:
I would not trust this deployment to enforce its stated time‑lock property in the presence of an operator‑controlled parent instance. The critical flaw allows the operator to set the host clock backwards and block drand beacons, making records decryptable immediately. Before trust could be placed, the time‑lock calculation must be changed to rely exclusively on verified drand beacons (refusing service when they are stale), removing any dependency on the host‑derived NSM timestamp. The rest of the design appears sound for confidentiality, integrity, and sender verification.