Skip to content

Commit b3a0bca

Browse files
committed
cvm: Only allow wihtelisted envs
1 parent f5e053d commit b3a0bca

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

dstack-types/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub struct AppCompose {
2525
pub local_key_provider_enabled: bool,
2626
#[serde(default)]
2727
pub key_provider: Option<KeyProviderKind>,
28+
#[serde(default)]
29+
pub allowed_envs: Vec<String>,
2830
}
2931

3032
#[derive(Deserialize, Serialize, Debug, Clone, Copy)]

tdxctl/src/fde_setup.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{
2-
collections::BTreeMap,
2+
collections::{BTreeMap, BTreeSet},
33
io::{Read, Write},
44
path::{Path, PathBuf},
55
process::{Command, Stdio},
@@ -318,7 +318,12 @@ impl SetupFdeArgs {
318318
deserialize_json_file(self.app_keys_file()).context("Failed to decode app keys")
319319
}
320320

321-
fn decrypt_env_vars(&self, key: &[u8], ciphertext: &[u8]) -> Result<BTreeMap<String, String>> {
321+
fn decrypt_env_vars(
322+
&self,
323+
key: &[u8],
324+
ciphertext: &[u8],
325+
allowed: &BTreeSet<String>,
326+
) -> Result<BTreeMap<String, String>> {
322327
let vars = if !key.is_empty() && !ciphertext.is_empty() {
323328
info!("Processing encrypted env");
324329
let env_crypt_key: [u8; 32] = key
@@ -327,7 +332,7 @@ impl SetupFdeArgs {
327332
.context("Invalid env crypt key length")?;
328333
let decrypted_json =
329334
dh_decrypt(env_crypt_key, ciphertext).context("Failed to decrypt env file")?;
330-
env_process::parse_env(&decrypted_json)?
335+
env_process::parse_env(&decrypted_json, allowed)?
331336
} else {
332337
info!("No encrypted env, using default");
333338
Default::default()
@@ -545,9 +550,18 @@ impl SetupFdeArgs {
545550
bail!("Failed to get valid key phrase from KMS");
546551
}
547552
host.notify_q("boot.progress", "decrypting env").await;
553+
let allowed_envs: BTreeSet<String> = host_shared
554+
.app_compose
555+
.allowed_envs
556+
.iter()
557+
.cloned()
558+
.collect();
548559
// Decrypt env file
549-
let decrypted_env =
550-
self.decrypt_env_vars(&app_keys.env_crypt_key, &host_shared.encrypted_env)?;
560+
let decrypted_env = self.decrypt_env_vars(
561+
&app_keys.env_crypt_key,
562+
&host_shared.encrypted_env,
563+
&allowed_envs,
564+
)?;
551565
let disk_key = hex::encode(&app_keys.disk_crypt_key);
552566
if is_bootstrapped {
553567
host.notify_q("boot.progress", "mounting rootfs").await;

tdxctl/src/fde_setup/env_process.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::{bail, Context, Result};
22
use serde::Deserialize;
3-
use std::collections::BTreeMap;
3+
use std::collections::{BTreeMap, BTreeSet};
4+
use tracing::warn;
45

56
fn escape_value(v: &str) -> String {
67
let mut needs_quotes = false;
@@ -41,7 +42,10 @@ struct Data {
4142
env: Vec<Pair>,
4243
}
4344

44-
pub fn parse_env(decrypted_json: &[u8]) -> Result<BTreeMap<String, String>> {
45+
pub fn parse_env(
46+
decrypted_json: &[u8],
47+
allowed: &BTreeSet<String>,
48+
) -> Result<BTreeMap<String, String>> {
4549
const MAX_ITEMS: usize = 1024;
4650
const MAX_TOTAL_SIZE: usize = 1024 * 1024;
4751

@@ -59,6 +63,10 @@ pub fn parse_env(decrypted_json: &[u8]) -> Result<BTreeMap<String, String>> {
5963
let mut total_size = 0;
6064

6165
for Pair { key, value } in data.env {
66+
if !allowed.contains(&key) {
67+
warn!("Skipping unauthorized environment variable: {key}");
68+
continue;
69+
}
6270
// Check key length (common Linux limit is 255)
6371
if key.len() > 255 {
6472
bail!("Environment variable name too long: {}", key);

teepod/src/console.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,8 @@ <h3>Derive VM</h3>
11031103
"tproxy_enabled": vmForm.value.tproxy_enabled,
11041104
"public_logs": vmForm.value.public_logs,
11051105
"public_sysinfo": vmForm.value.public_sysinfo,
1106-
"local_key_provider_enabled": vmForm.value.local_key_provider_enabled
1106+
"local_key_provider_enabled": vmForm.value.local_key_provider_enabled,
1107+
"allowed_envs": vmForm.value.encrypted_envs.map(env => env.key),
11071108
};
11081109

11091110
if (vmForm.value.preLaunchScript?.trim()) {

0 commit comments

Comments
 (0)