From bbcfd368bf330f63ac69a570530cbd3646d54987 Mon Sep 17 00:00:00 2001 From: nicochow Date: Wed, 2 Sep 2026 19:05:50 +0800 Subject: [PATCH] fix(sandbox): scrub SSH_AUTH_SOCK from the sandbox subprocess env (#5145) SSH_AUTH_SOCK points at the host's ssh-agent socket. A sandbox subprocess that inherits it can sign and authenticate with every key the agent holds (git push, ssh logins) without reading any key file -- the same credential-pointer leak class as the *_ASKPASS helpers the env policy already scrubs deliberately. No wildcard pattern fits (*AUTH* would strip benign names), so add an exact entry to _BLOCKED_EXACT_NAMES. A skill that genuinely needs the agent socket can still declare it via required-secrets: injected values win over the blocklist by design. Co-authored-by: zhouyujie --- backend/packages/harness/deerflow/sandbox/env_policy.py | 8 ++++++++ backend/tests/test_skill_request_scoped_secrets.py | 3 +++ 2 files changed, 11 insertions(+) diff --git a/backend/packages/harness/deerflow/sandbox/env_policy.py b/backend/packages/harness/deerflow/sandbox/env_policy.py index 6381c7d7d..b0eae3b98 100644 --- a/backend/packages/harness/deerflow/sandbox/env_policy.py +++ b/backend/packages/harness/deerflow/sandbox/env_policy.py @@ -84,6 +84,14 @@ _BLOCKED_EXACT_NAMES: frozenset[str] = frozenset( "REDISCLI_AUTH", "REDIS_AUTH", "PGSERVICEFILE", + # ``SSH_AUTH_SOCK`` points at the host's ssh-agent socket. A sandbox + # subprocess that inherits it can sign and authenticate with every key + # the agent holds (git push, ssh logins) without ever reading a key + # file — the same credential-*pointer* leak class as the ``*_ASKPASS`` + # helpers deliberately scrubbed by ``*PASS*`` above. No wildcard fits + # (``*AUTH*`` would strip benign names and ``SOCK`` is not unique to + # credentials), so it needs an exact entry. + "SSH_AUTH_SOCK", } ) diff --git a/backend/tests/test_skill_request_scoped_secrets.py b/backend/tests/test_skill_request_scoped_secrets.py index 2a199c7b2..1675b9d81 100644 --- a/backend/tests/test_skill_request_scoped_secrets.py +++ b/backend/tests/test_skill_request_scoped_secrets.py @@ -191,6 +191,9 @@ class TestEnvPolicy: "GIT_ASKPASS", "SSH_ASKPASS", "SUDO_ASKPASS", + # ssh-agent socket: a credential pointer like the ASKPASS helpers — + # inheriting it lets the sandbox sign with every key the agent holds. + "SSH_AUTH_SOCK", ], ) def test_secret_like_names_are_blocked(self, name):