Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions charts/openab/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ Agents deployed:
kubectl rollout restart deployment/{{ include "openab.agentFullname" (dict "ctx" $ "agent" $name) }}
{{- end }}
{{- end }}

⚠️ SECURITY: The agent subprocess only receives HOME, PATH, and explicitly configured [agent].env vars.
Any env var passed via [agent].env is accessible to the agent and could be exfiltrated via prompt injection.
All supported backends use OAuth/file-based auth — avoid passing API keys via env vars when possible.
4 changes: 4 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ working_dir = "/home/agent"
# command = "claude"
# args = ["--acp"]
# working_dir = "/home/agent"
# ⚠️ SECURITY WARNING: Any env var listed here is accessible to the agent.
# A user could trick the agent into leaking these values via prompt injection.
# All supported backends support OAuth login — prefer that over env var API keys.
# Note: env vars here can override baseline vars (HOME, PATH, USER) if needed.
# env = { ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}" }

# [agent]
Expand Down
28 changes: 28 additions & 0 deletions src/acp/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,37 @@ impl AcpConnection {
{
cmd.creation_flags(0x00000200); // CREATE_NEW_PROCESS_GROUP
}
// Clear inherited env to prevent credential leakage (e.g. DISCORD_BOT_TOKEN).
// Only [agent].env values + essential baseline vars are passed through.
cmd.env_clear();
// Preserve the real HOME so agents can find OAuth/auth files (~/.codex,
// ~/.claude, ~/.config/gh, etc.). working_dir is already set via
// current_dir() above and is not necessarily the user's home directory.
cmd.env("HOME", std::env::var("HOME").unwrap_or_else(|_| working_dir.into()));
cmd.env("PATH", std::env::var("PATH").unwrap_or_else(|_| "/usr/local/bin:/usr/bin:/bin".into()));
#[cfg(unix)]
{
cmd.env("USER", std::env::var("USER").unwrap_or_else(|_| "agent".into()));
}
#[cfg(windows)]
{
// Windows requires SystemRoot for DLL loading and basic OS functionality.
// USERPROFILE is the Windows equivalent of HOME.
cmd.env("USERPROFILE", std::env::var("USERPROFILE").unwrap_or_else(|_| working_dir.into()));
cmd.env("USERNAME", std::env::var("USERNAME").unwrap_or_else(|_| "agent".into()));
if let Ok(v) = std::env::var("SystemRoot") { cmd.env("SystemRoot", v); }
if let Ok(v) = std::env::var("SystemDrive") { cmd.env("SystemDrive", v); }
}
for (k, v) in env {
cmd.env(k, expand_env(v));
}
if !env.is_empty() {
let keys: Vec<&String> = env.keys().collect();
tracing::warn!(
?keys,
"[agent].env is set -- these values are accessible to the agent and could be exfiltrated via prompt injection"
);
}
let mut proc = cmd
.spawn()
.map_err(|e| anyhow!("failed to spawn {command}: {e}"))?;
Expand Down
Loading