Skip to content

Commit 53697dd

Browse files
JAORMXclaude
andcommitted
Enable git operations inside sandbox VMs
Add openssh-client to the base guest image so git can use SSH protocol with the already-implemented SSH agent forwarding. Allow github.com:22 in standard egress profile (DNS-scoped, no lateral movement risk). Set GIT_TERMINAL_PROMPT=0 to prevent git from hanging on credential prompts — public repos clone anonymously, private repos fail cleanly without a token. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 968d98d commit 53697dd

4 files changed

Lines changed: 12 additions & 4 deletions

File tree

images/base/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ RUN apk add --no-cache \
1515
grep \
1616
sed \
1717
gawk \
18-
curl
18+
curl \
19+
openssh-client
1920

2021
# Ensure /usr/local/bin exists (not present in Wolfi by default)
2122
RUN mkdir -p /usr/local/bin

internal/infra/agent/registry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313

1414
// Common dev infrastructure hosts shared across agents at the standard profile.
1515
var devInfraHosts = []egress.Host{
16-
{Name: "github.com", Ports: []uint16{443}},
16+
{Name: "github.com", Ports: []uint16{443, 22}},
1717
{Name: "api.github.com", Ports: []uint16{443}},
1818
{Name: "*.githubusercontent.com", Ports: []uint16{443}},
1919
{Name: "registry.npmjs.org", Ports: []uint16{443}},

pkg/sandbox/sandbox.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,13 @@ func (s *SandboxRunner) Prepare(ctx context.Context, agentName string, opts RunO
314314
}
315315
}
316316

317+
// Prevent git from hanging on interactive credential prompts inside the VM.
318+
// Public repos work anonymously; private repos fail cleanly without a token.
319+
if envVars == nil {
320+
envVars = make(map[string]string)
321+
}
322+
envVars["GIT_TERMINAL_PROMPT"] = "0"
323+
317324
// Determine if a GitHub token is available for credential helper injection.
318325
hasGitToken := opts.GitTokenEnabled && (envVars["GITHUB_TOKEN"] != "" || envVars["GH_TOKEN"] != "")
319326

pkg/sandbox/sandbox_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func TestSandboxRunner_Run(t *testing.T) {
218218
assert.Equal(t, uint32(2), vmRunner.startCfg.CPUs)
219219
assert.Equal(t, uint32(2048), vmRunner.startCfg.Memory)
220220
assert.Equal(t, "/tmp/workspace", vmRunner.startCfg.WorkspacePath)
221-
assert.Equal(t, map[string]string{"TEST_KEY": "secret123"}, vmRunner.startCfg.EnvVars)
221+
assert.Equal(t, map[string]string{"TEST_KEY": "secret123", "GIT_TERMINAL_PROMPT": "0"}, vmRunner.startCfg.EnvVars)
222222

223223
// Verify terminal session was started.
224224
assert.Equal(t, "127.0.0.1", sessionRunner.runOpts.Host)
@@ -693,7 +693,7 @@ func TestSandboxRunner_Prepare_Success(t *testing.T) {
693693
assert.Equal(t, "sandbox-test-agent", sb.VMConfig.Name)
694694
assert.Equal(t, snapshotDir, sb.WorkspacePath)
695695
assert.NotNil(t, sb.Snapshot)
696-
assert.Equal(t, map[string]string{"TEST_KEY": "secret123"}, sb.EnvVars)
696+
assert.Equal(t, map[string]string{"TEST_KEY": "secret123", "GIT_TERMINAL_PROMPT": "0"}, sb.EnvVars)
697697
assert.Equal(t, snapshot.NopMatcher, sb.DiffMatcher)
698698
assert.Equal(t, snapshotDir, vmRunner.startCfg.WorkspacePath)
699699
assert.True(t, cloner.createCalled)

0 commit comments

Comments
 (0)