mirror of
https://github.com/anthropic-experimental/sandbox-runtime.git
synced 2026-05-06 21:52:30 +08:00
test(integration): swap allowedDomains via updateConfig instead of reset+initialize
The wildcard-domain test was the only test in its describe block that tore down and rebuilt the entire proxy/bridge stack (twice) — every other test reuses the bridge from beforeAll. On the linux/x86-64 CI runner this test has been intermittently hitting the 5s test timeout, and once it does, bun's dangling-process cleanup kills the freshly spawned socat bridge, which cascades into the next test failing with "HTTP bridge socket does not exist" and the following beforeAll hook timing out. The test only needs a different allowedDomains list. updateConfig() swaps the singleton config in-place and the proxy filter reads it on every request, so we get the same coverage without any lifecycle churn. Restore the original config in a finally block. Also tighten the one curl that actually reaches an upstream (api.github.com) — the assertion only checks the proxy did not block it, so the response body is irrelevant.
This commit is contained in:
@@ -773,83 +773,84 @@ describe.if(isLinux)('Sandbox Integration Tests', () => {
|
||||
})
|
||||
|
||||
it('should enforce wildcard domain pattern matching correctly', async () => {
|
||||
// Reset and reinitialize with wildcard pattern
|
||||
await SandboxManager.reset()
|
||||
await SandboxManager.initialize({
|
||||
// Swap allowedDomains in-place rather than reset()+initialize().
|
||||
// The proxy filter reads the live config on every request, so this
|
||||
// takes effect immediately and lets us keep the bridge/proxy that
|
||||
// every other test in this describe already uses.
|
||||
const baseConfig = createTestConfig(TEST_DIR)
|
||||
SandboxManager.updateConfig({
|
||||
...baseConfig,
|
||||
network: {
|
||||
...baseConfig.network,
|
||||
allowedDomains: ['*.github.com', 'example.com'],
|
||||
deniedDomains: [],
|
||||
},
|
||||
filesystem: {
|
||||
denyRead: [],
|
||||
allowWrite: [],
|
||||
denyWrite: [],
|
||||
},
|
||||
})
|
||||
try {
|
||||
// Test 1: Subdomain should match wildcard. We only assert the
|
||||
// proxy did NOT block it — the upstream response is irrelevant —
|
||||
// so cap the request tightly.
|
||||
const command1 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --connect-timeout 2 --max-time 2 http://api.github.com 2>&1 | head -20',
|
||||
)
|
||||
|
||||
// Test 1: Subdomain should match wildcard
|
||||
const command1 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 3 http://api.github.com 2>&1 | head -20',
|
||||
)
|
||||
const result1 = spawnSync(command1, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 3000,
|
||||
})
|
||||
|
||||
const result1 = spawnSync(command1, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 5000,
|
||||
})
|
||||
// Should NOT be blocked - api.github.com matches *.github.com
|
||||
const output1 = result1.stdout.toLowerCase()
|
||||
expect(output1).not.toContain('blocked by network allowlist')
|
||||
|
||||
// Should NOT be blocked - api.github.com matches *.github.com
|
||||
const output1 = result1.stdout.toLowerCase()
|
||||
expect(output1).not.toContain('blocked by network allowlist')
|
||||
// Test 2: Base domain should NOT match wildcard (*.github.com doesn't match github.com)
|
||||
const command2 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 2 http://github.com 2>&1',
|
||||
)
|
||||
|
||||
// Test 2: Base domain should NOT match wildcard (*.github.com doesn't match github.com)
|
||||
const command2 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 2 http://github.com 2>&1',
|
||||
)
|
||||
const result2 = spawnSync(command2, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 3000,
|
||||
})
|
||||
|
||||
const result2 = spawnSync(command2, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 3000,
|
||||
})
|
||||
// Should be blocked - github.com does NOT match *.github.com
|
||||
const output2 = result2.stdout.toLowerCase()
|
||||
expect(output2).toContain('blocked by network allowlist')
|
||||
|
||||
// Should be blocked - github.com does NOT match *.github.com
|
||||
const output2 = result2.stdout.toLowerCase()
|
||||
expect(output2).toContain('blocked by network allowlist')
|
||||
// Test 3: Malicious lookalike domain should NOT match
|
||||
const command3 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 2 http://malicious-github.com 2>&1',
|
||||
)
|
||||
|
||||
// Test 3: Malicious lookalike domain should NOT match
|
||||
const command3 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 2 http://malicious-github.com 2>&1',
|
||||
)
|
||||
const result3 = spawnSync(command3, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 3000,
|
||||
})
|
||||
|
||||
const result3 = spawnSync(command3, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 3000,
|
||||
})
|
||||
// Should be blocked - malicious-github.com does NOT match *.github.com
|
||||
const output3 = result3.stdout.toLowerCase()
|
||||
expect(output3).toContain('blocked by network allowlist')
|
||||
|
||||
// Should be blocked - malicious-github.com does NOT match *.github.com
|
||||
const output3 = result3.stdout.toLowerCase()
|
||||
expect(output3).toContain('blocked by network allowlist')
|
||||
// Test 4: Multiple subdomains should match
|
||||
const command4 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 3 http://raw.githubusercontent.com 2>&1 | head -20',
|
||||
)
|
||||
|
||||
// Test 4: Multiple subdomains should match
|
||||
const command4 = await SandboxManager.wrapWithSandbox(
|
||||
'curl -s --max-time 3 http://raw.githubusercontent.com 2>&1 | head -20',
|
||||
)
|
||||
const result4 = spawnSync(command4, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 5000,
|
||||
})
|
||||
|
||||
const result4 = spawnSync(command4, {
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
timeout: 5000,
|
||||
})
|
||||
|
||||
// githubusercontent.com should be blocked (doesn't match *.github.com)
|
||||
const output4 = result4.stdout.toLowerCase()
|
||||
expect(output4).toContain('blocked by network allowlist')
|
||||
|
||||
// Restore original config
|
||||
await SandboxManager.reset()
|
||||
await SandboxManager.initialize(createTestConfig(TEST_DIR))
|
||||
// githubusercontent.com should be blocked (doesn't match *.github.com)
|
||||
const output4 = result4.stdout.toLowerCase()
|
||||
expect(output4).toContain('blocked by network allowlist')
|
||||
} finally {
|
||||
// Restore the suite's default allowlist for subsequent tests.
|
||||
SandboxManager.updateConfig(baseConfig)
|
||||
}
|
||||
})
|
||||
|
||||
it('should prevent creation of special file types that could bypass restrictions', async () => {
|
||||
|
||||
Reference in New Issue
Block a user