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
6 changes: 6 additions & 0 deletions omnigent/host/connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,12 @@ def _url_is_loopback(url: str) -> bool:
# not match what the host owner configured (e.g. a non-standard
# kubeconfig location or a colon-separated multi-file list).
"KUBECONFIG",
# ssh-agent socket path. Same class as KUBECONFIG above: a path to a
# unix socket, not a bearer secret. Without it every runner-spawned
# context (sys_os_shell, terminal panes, coding sub-agents) loses
# ssh-agent auth, so git-over-SSH and SSH-cert-authenticated tooling
# fail with "dial unix: missing address".
"SSH_AUTH_SOCK",
# Telemetry master opt-in. MUST propagate, or the daemon-spawned runner
# (and the harness it spawns) never see OMNIGENT_TELEMETRY_ENABLED, so
# telemetry.init() no-ops there and omni-runner / omni-harness export
Expand Down
6 changes: 6 additions & 0 deletions omnigent/inner/agent_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
# without it a corporate-CA user upgrading would hit TLS failures from
# every harness that does not happen to own a NODE_ prefix of its own.
"NODE_EXTRA_CA_CERTS",
# ssh-agent socket path, so an agent's git-over-SSH and SSH-cert
# tooling authenticates. A path to a unix socket, not a bearer token:
# reaching the agent still requires the user's own ssh-agent to be
# running and to hold the key. Shared here because every harness runs
# git, not just the one whose bug surfaced it.
"SSH_AUTH_SOCK",
OMNIGENT_SESSION_ENV_VAR,
}
)
Expand Down
9 changes: 7 additions & 2 deletions omnigent/inner/os_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,13 @@ class _PopenKwargs(TypedDict, total=False):
# non-interactive startup.
# - ``PROMPT_COMMAND``: arbitrary command run by bash before each prompt.
# - ``CDPATH``: changes the resolution of relative paths in shell ``cd``.
# - ``SSH_AUTH_SOCK``: the user's running ssh-agent socket — a
# credential surface masquerading as a path.
# - ``SSH_AUTH_SOCK``: the user's ssh-agent socket. Allowed through the
# weaker host→runner and harness-CLI boundaries (a socket path, like
# ``KUBECONFIG``), but an ACTIVE sandbox is where the agent is being
# deliberately confined, and signing with the user's keys is exactly
# what that confinement is for. Opt in per-spec, and grant the socket
# path too: under seatbelt / bwrap the name alone points at something
# unreachable.
# - ``DBUS_SESSION_BUS_ADDRESS``: lets the helper talk to the user's
# D-Bus session.
# - ``XDG_RUNTIME_DIR``: per-session socket directory (Wayland, ssh-
Expand Down
5 changes: 5 additions & 0 deletions tests/host/test_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2055,6 +2055,7 @@ def test_build_runner_env_allowlists_host_env_and_strips_secrets() -> None:
"SOME_RANDOM_VAR": "x",
"OMNIGENT_CLAUDE_SDK_NO_SANDBOX": "1",
"KUBECONFIG": "/home/alice/.kube/config",
"SSH_AUTH_SOCK": "/private/tmp/com.apple.launchd.7Qk/Listeners",
"CLAUDE_CODE_SKIP_BEDROCK_AUTH": "1",
"OMNIGENT_DATABRICKS_EXTRA_HEADERS": '{"x-databricks-route-hint": "instance-abc"}',
"OMNIGENT_LOG_LEVEL": "DEBUG",
Expand Down Expand Up @@ -2101,6 +2102,10 @@ def test_build_runner_env_allowlists_host_env_and_strips_secrets() -> None:
# KUBECONFIG is a filesystem path (not a secret) — kubectl, helm, k9s
# need it to resolve the user's cluster contexts and namespaces.
assert env["KUBECONFIG"] == "/home/alice/.kube/config"
# SSH_AUTH_SOCK is a socket path on the same footing. Dropping it leaves
# every runner-spawned context without ssh-agent auth, so git-over-SSH and
# SSH-cert tooling fail with "dial unix: missing address".
assert env["SSH_AUTH_SOCK"] == "/private/tmp/com.apple.launchd.7Qk/Listeners"
# CLAUDE_CODE_SKIP_BEDROCK_AUTH disables AWS SigV4 auth for LiteLLM
# proxies — a non-secret boolean, same rationale as CLAUDE_CODE_USE_BEDROCK.
assert env["CLAUDE_CODE_SKIP_BEDROCK_AUTH"] == "1"
Expand Down
8 changes: 8 additions & 0 deletions tests/test_agent_spawn_env_canary.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ def test_real_builders_pass_node_extra_ca_certs(monkeypatch):
assert env.get("NODE_EXTRA_CA_CERTS") == "/etc/corp-ca.pem", harness


def test_real_builders_pass_ssh_auth_sock(monkeypatch):
"""ssh-agent must survive filtering, or git-over-SSH breaks in every harness."""
sock = "/private/tmp/com.apple.launchd.7Qk/Listeners"
monkeypatch.setattr("os.environ", {"SSH_AUTH_SOCK": sock})
for harness, build in sorted(SPAWN_ENV_BUILDERS.items()):
assert build().get("SSH_AUTH_SOCK") == sock, harness


@pytest.mark.parametrize("harness", sorted(HARNESS_PREFIXES))
def test_no_harness_inherits_unrelated_secrets(harness, hostile_env):
env = clean_agent_env(allow_prefixes=HARNESS_PREFIXES[harness], source=hostile_env)
Expand Down
Loading