Conversation
Describes the X25519 + AES-256-GCM scheme used to protect app environment variables, including key derivation from KMS, the .appkeys.json file format, and cross-language encrypt/decrypt implementation guides (Rust, Go, Python, TypeScript).
kvinwang
left a comment
There was a problem hiding this comment.
Review: Missing Security Caveat — Encrypted Env Lacks Origin Authentication
The spec accurately documents the encryption/decryption protocol, but as a technical specification it has an obligation to clearly state the security boundary of this scheme. Currently it only describes confidentiality, without warning that there is no origin authentication.
The Problem
The encryption public key is derived from app_id, which is a public value (SHA256(app-compose.json)[0..20]). Anyone who knows the app_id can:
- Call
VMM.GetAppEnvEncryptPubKey({ app_id })to get the public key - Encrypt arbitrary env vars with it
- Submit the encrypted payload to the VMM
The CVM will happily decrypt and use these forged env vars. The ECIES scheme guarantees confidentiality (only the TEE can decrypt), but provides zero authenticity — the CVM cannot distinguish between env vars from the legitimate developer and env vars from a malicious host operator or other attacker.
What's Already Documented Elsewhere
This limitation is already acknowledged in:
docs/security/security-model.md§"Environment variables need application-layer authentication"docs/security/security-best-practices.md§"Authenticated envs and user_config"
But a standalone spec document should not rely on readers having seen those pages.
Suggested Addition
Add a Security Considerations section (before or after "End-to-End Flow"):
## Security Considerations
### Encryption provides confidentiality, not origin authentication
The encrypted env scheme guarantees that only the target CVM (via its TEE-held private
key) can decrypt the environment variables. However, it does **not** authenticate who
encrypted them. Since the encryption public key is derivable from the public `app_id`,
**anyone** can encrypt and submit env vars to the CVM.
This means a malicious host operator (or any party with VMM access) could replace
the encrypted env payload with their own. The CVM will decrypt and use the replacement
without detecting the substitution.
### Developer responsibility: application-layer authentication
Developers **must** implement origin verification for encrypted env vars. Recommended
approaches:
1. **`APP_LAUNCH_TOKEN` pattern** (built-in support): Include a secret token as an
encrypted env var. Its SHA256 hash is embedded in `app-compose.json`
(`launch_token_hash` field), which is measured into the TDX attestation. A prelaunch
script verifies the token hash before the app starts. The VMM UI auto-generates
this prelaunch script — developers only need to add the `APP_LAUNCH_TOKEN` env var.
See [security-best-practices.md](./security/security-best-practices.md#authenticated-envs-and-user_config).
2. **Custom signing**: Sign the env var payload with a key known only to the developer,
and verify the signature inside the app at startup.
3. **Embedded secret**: Include a shared secret (known only to the developer and the
app) in the encrypted env vars, and verify its presence at runtime.
For full guidance, see [security-best-practices.md](./security/security-best-practices.md)
and [security-model.md](./security/security-model.md#environment-variables-need-application-layer-authentication).Other Observations
-
Spec accuracy: The protocol details (X25519 + AES-256-GCM, no KDF, ciphertext format, key derivation chain) are consistent with the source code in
dstack-util/src/crypto.rsandkms/src/main_service.rs. The protobuf definitions includingsignature_v1also match. -
Minor: HKDF salt not mentioned: The key derivation uses HKDF-SHA256 with salt
b"RATLS"internally. This is an implementation detail but could be noted for completeness. -
user_configparallel: The best practices doc also notes thatuser_confighas the same authenticity problem. Consider mentioning this in the spec ifuser_configinteracts with encrypted env in any way.
Summary
docs/encrypted-env-spec.mddocumenting the X25519 + AES-256-GCM scheme used to encrypt/decrypt application environment variables.appkeys.jsonfile format and hex-encoded field conventionsTest plan
dstack-util/src/crypto.rs,kms/src/main_service.rs, SDK implementations)