Skip to content

Commit 82728be

Browse files
ammarioclaude
andcommitted
Fix environment variable passing through su in Linux jail
When using su to drop privileges in Linux jail, environment variables set via cmd.env() were not being preserved properly. This caused TLS certificate validation to fail because CA certificate environment variables weren't reaching the child process. The fix explicitly exports environment variables in the shell command passed to su -c, ensuring they're available in the dropped-privilege context. - Export env vars explicitly in shell command for su - Use proper shell escaping for values with special characters - Preserve SUDO_* environment variables for consistency 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 27a4273 commit 82728be

1 file changed

Lines changed: 72 additions & 4 deletions

File tree

src/jail/linux/mod.rs

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -634,21 +634,89 @@ impl Jail for LinuxJail {
634634
self.namespace_name, command
635635
);
636636

637+
// Check if we're running as root and should drop privileges
638+
let current_uid = unsafe { libc::getuid() };
639+
let target_user = if current_uid == 0 {
640+
// Running as root - check for SUDO_USER to drop privileges to original user
641+
std::env::var("SUDO_USER").ok()
642+
} else {
643+
// Not root - no privilege dropping needed
644+
None
645+
};
646+
647+
if let Some(ref user) = target_user {
648+
debug!(
649+
"Will drop to user '{}' (from SUDO_USER) after entering namespace",
650+
user
651+
);
652+
}
653+
637654
// Build command: ip netns exec <namespace> <command>
655+
// If we need to drop privileges, we wrap with su
638656
let mut cmd = Command::new("ip");
639657
cmd.args(["netns", "exec", &self.namespace_name]);
640658

641-
// Add the actual command
642-
cmd.arg(&command[0]);
643-
for arg in &command[1..] {
644-
cmd.arg(arg);
659+
if let Some(user) = target_user {
660+
// Use su to drop privileges to the original user
661+
// We need to pass environment variables explicitly since su might not preserve them all
662+
cmd.arg("su");
663+
cmd.arg("-s"); // Specify shell explicitly
664+
cmd.arg("/bin/sh"); // Use sh for compatibility
665+
cmd.arg("-p"); // Preserve environment
666+
cmd.arg(&user); // Username from SUDO_USER
667+
cmd.arg("-c"); // Execute command
668+
669+
// Build shell command with explicit environment exports
670+
let mut shell_command = String::new();
671+
672+
// Export environment variables explicitly in the shell command
673+
for (key, value) in extra_env {
674+
// Escape the value for shell safety
675+
let escaped_value = value.replace('\'', "'\\''");
676+
shell_command.push_str(&format!("export {}='{}'; ", key, escaped_value));
677+
}
678+
679+
// Add the actual command
680+
shell_command.push_str(
681+
&command
682+
.iter()
683+
.map(|arg| {
684+
// Simple escaping: wrap in single quotes and escape existing single quotes
685+
if arg.contains('\'') {
686+
format!("\"{}\"", arg.replace('"', "\\\""))
687+
} else {
688+
format!("'{}'", arg)
689+
}
690+
})
691+
.collect::<Vec<_>>()
692+
.join(" "),
693+
);
694+
695+
cmd.arg(shell_command);
696+
} else {
697+
// No privilege dropping needed, execute directly
698+
cmd.arg(&command[0]);
699+
for arg in &command[1..] {
700+
cmd.arg(arg);
701+
}
645702
}
646703

647704
// Set environment variables
648705
for (key, value) in extra_env {
649706
cmd.env(key, value);
650707
}
651708

709+
// Preserve SUDO environment variables for consistency with macOS
710+
if let Ok(sudo_user) = std::env::var("SUDO_USER") {
711+
cmd.env("SUDO_USER", sudo_user);
712+
}
713+
if let Ok(sudo_uid) = std::env::var("SUDO_UID") {
714+
cmd.env("SUDO_UID", sudo_uid);
715+
}
716+
if let Ok(sudo_gid) = std::env::var("SUDO_GID") {
717+
cmd.env("SUDO_GID", sudo_gid);
718+
}
719+
652720
// Note: We do NOT set HTTP_PROXY/HTTPS_PROXY environment variables here.
653721
// The jail uses iptables rules to transparently redirect traffic to the proxy,
654722
// making it work with applications that don't respect proxy environment variables.

0 commit comments

Comments
 (0)