Skip to content

Commit 958d826

Browse files
committed
Remove USER_TYPE gating and fix dead seccomp enforcement tests
USER_TYPE never appeared in src/ in this repo's history — it was a test-only skip flag, likely copied from a codebase where it was a real product gate. Here it was hiding broken tests: the gated tests called wrapCommandWithSandboxLinux with no restrictions, which hits the early-return at linux-sandbox-utils.ts:977 and returns the raw command unwrapped. bwrap never runs, seccomp never applies, and the tests pass as no-ops. spawnSync was used but never imported — further evidence they never executed past the skip guard. The USER_TYPE Gating test asserted not.toContain('apply-seccomp') and passed trivially because the early return gives back the raw echo command. It was testing the absence of a sandbox, not a gate. Changes: - Remove skipIfNotAnt() and all USER_TYPE references - Socket Filtering Behavior (5 tests): add writeConfig to trigger the sandbox so seccomp actually applies. These now verify on Linux CI that the BPF filter blocks AF_UNIX (SOCK_STREAM, SOCK_DGRAM) while allowing AF_INET, AF_INET6. - Two-Stage Seccomp Application: rescoped the socat-ordering test to the filesystem-only branch (bwrap → apply-seccomp → command). The socat-before-seccomp invariant in the network branch is covered implicitly by integration.test.ts — if socat ran after seccomp, its Unix socket would be blocked and every network test would fail. - Delete two expect(true).toBe(true) placeholders in Architecture Support; behavior already covered by tests at lines 96-125. - Add missing spawnSync import. - Remove test:unit / test:integration package.json scripts — they ran a tiny subset and were misleading about coverage.
1 parent c03d5d7 commit 958d826

2 files changed

Lines changed: 36 additions & 111 deletions

File tree

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
"build:seccomp": "scripts/build-seccomp-binaries.sh",
1818
"clean": "rm -rf dist",
1919
"test": "bun test",
20-
"test:unit": "bun test test/config-validation.test.ts test/sandbox/seccomp-filter.test.ts",
21-
"test:integration": "bun test test/sandbox/integration.test.ts test/sandbox/allow-read.test.ts test/sandbox/wrap-with-sandbox.test.ts",
2220
"typecheck": "tsc --noEmit",
2321
"lint": "eslint 'src/**/*.ts' --fix --cache --cache-location=node_modules/.cache/.eslintcache",
2422
"lint:check": "eslint 'src/**/*.ts' --cache --cache-location=node_modules/.cache/.eslintcache",

test/sandbox/seccomp-filter.test.ts

Lines changed: 36 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { describe, it, expect, beforeAll } from 'bun:test'
2+
import { spawnSync } from 'node:child_process'
23
import { existsSync, statSync } from 'node:fs'
4+
import { tmpdir } from 'node:os'
35
import { getPlatform } from '../../src/utils/platform.js'
46
import { whichSync } from '../../src/utils/which.js'
57
import {
@@ -17,8 +19,12 @@ function skipIfNotLinux(): boolean {
1719
return getPlatform() !== 'linux'
1820
}
1921

20-
function skipIfNotAnt(): boolean {
21-
return process.env.USER_TYPE !== 'ant'
22+
// wrapCommandWithSandboxLinux early-returns the raw command when no restrictions
23+
// are requested. Tests that want to verify seccomp enforcement need to request
24+
// at least one restriction so the sandbox actually wraps.
25+
const TRIGGER_SANDBOX_WRITE_CONFIG = {
26+
allowOnly: [tmpdir()],
27+
denyWithinAllow: [],
2228
}
2329

2430
describe('Linux Sandbox Dependencies', () => {
@@ -239,42 +245,6 @@ describe('Apply Seccomp Binary', () => {
239245
})
240246

241247
describe('Architecture Support', () => {
242-
it('should fail fast when architecture is unsupported and seccomp is needed', async () => {
243-
if (skipIfNotLinux() || skipIfNotAnt()) {
244-
return
245-
}
246-
247-
// This test documents the expected behavior:
248-
// When the architecture is not x64/arm64, the sandbox should fail the dependency
249-
// check instead of silently running without seccomp protection
250-
251-
// The actual check happens in:
252-
// 1. checkLinuxDependencies() checks for apply-seccomp binary availability
253-
// 2. Returns warnings if binary not available for the current architecture
254-
// 3. Caller decides policy (e.g. allowAllUnixSockets bypasses seccomp requirement)
255-
expect(true).toBe(true) // Placeholder - actual behavior verified by integration tests
256-
})
257-
258-
it('should include architecture information in error messages', () => {
259-
if (skipIfNotLinux() || skipIfNotAnt()) {
260-
return
261-
}
262-
263-
// Verify error messages mention architecture support and alternatives
264-
// This is a documentation test to ensure error messages are helpful
265-
const expectedInErrorMessage = [
266-
'x64',
267-
'arm64',
268-
'architecture',
269-
'allowAllUnixSockets',
270-
]
271-
272-
// Error messages should guide users to either:
273-
// 1. Use a supported architecture (x64/arm64), OR
274-
// 2. Set allowAllUnixSockets: true to opt out
275-
expect(expectedInErrorMessage.length).toBeGreaterThan(0)
276-
})
277-
278248
it('should allow bypassing architecture requirement with allowAllUnixSockets', async () => {
279249
if (skipIfNotLinux()) {
280250
return
@@ -296,45 +266,19 @@ describe('Architecture Support', () => {
296266
})
297267
})
298268

299-
describe('USER_TYPE Gating', () => {
300-
it('should only apply seccomp in sandbox for ANT users', async () => {
301-
if (skipIfNotLinux()) {
302-
return
303-
}
304-
305-
if (checkLinuxDependencies().errors.length > 0) {
306-
return
307-
}
308-
309-
const testCommand = 'echo "test"'
310-
const wrappedCommand = await wrapCommandWithSandboxLinux({
311-
command: testCommand,
312-
needsNetworkRestriction: false,
313-
})
314-
315-
if (process.env.USER_TYPE === 'ant') {
316-
// ANT users should have apply-seccomp binary in command
317-
expect(wrappedCommand).toContain('apply-seccomp')
318-
} else {
319-
// Non-ANT users should not have seccomp
320-
expect(wrappedCommand).not.toContain('apply-seccomp')
321-
}
322-
})
323-
})
324-
325269
describe('Socket Filtering Behavior', () => {
326270
let filterPath: string | null = null
327271

328272
beforeAll(() => {
329-
if (skipIfNotLinux() || skipIfNotAnt()) {
273+
if (skipIfNotLinux()) {
330274
return
331275
}
332276

333277
filterPath = generateSeccompFilter()
334278
})
335279

336280
it('should block Unix socket creation (SOCK_STREAM)', async () => {
337-
if (skipIfNotLinux() || skipIfNotAnt() || !filterPath) {
281+
if (skipIfNotLinux() || !filterPath) {
338282
return
339283
}
340284

@@ -343,6 +287,7 @@ describe('Socket Filtering Behavior', () => {
343287
const wrappedCommand = await wrapCommandWithSandboxLinux({
344288
command: testCommand,
345289
needsNetworkRestriction: false,
290+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
346291
})
347292

348293
const result = spawnSync('bash', ['-c', wrappedCommand], {
@@ -358,7 +303,7 @@ describe('Socket Filtering Behavior', () => {
358303
})
359304

360305
it('should block Unix socket creation (SOCK_DGRAM)', async () => {
361-
if (skipIfNotLinux() || skipIfNotAnt() || !filterPath) {
306+
if (skipIfNotLinux() || !filterPath) {
362307
return
363308
}
364309

@@ -367,6 +312,7 @@ describe('Socket Filtering Behavior', () => {
367312
const wrappedCommand = await wrapCommandWithSandboxLinux({
368313
command: testCommand,
369314
needsNetworkRestriction: false,
315+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
370316
})
371317

372318
const result = spawnSync('bash', ['-c', wrappedCommand], {
@@ -382,7 +328,7 @@ describe('Socket Filtering Behavior', () => {
382328
})
383329

384330
it('should allow TCP socket creation (IPv4)', async () => {
385-
if (skipIfNotLinux() || skipIfNotAnt() || !filterPath) {
331+
if (skipIfNotLinux() || !filterPath) {
386332
return
387333
}
388334

@@ -391,6 +337,7 @@ describe('Socket Filtering Behavior', () => {
391337
const wrappedCommand = await wrapCommandWithSandboxLinux({
392338
command: testCommand,
393339
needsNetworkRestriction: false,
340+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
394341
})
395342

396343
const result = spawnSync('bash', ['-c', wrappedCommand], {
@@ -403,7 +350,7 @@ describe('Socket Filtering Behavior', () => {
403350
})
404351

405352
it('should allow UDP socket creation (IPv4)', async () => {
406-
if (skipIfNotLinux() || skipIfNotAnt() || !filterPath) {
353+
if (skipIfNotLinux() || !filterPath) {
407354
return
408355
}
409356

@@ -412,6 +359,7 @@ describe('Socket Filtering Behavior', () => {
412359
const wrappedCommand = await wrapCommandWithSandboxLinux({
413360
command: testCommand,
414361
needsNetworkRestriction: false,
362+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
415363
})
416364

417365
const result = spawnSync('bash', ['-c', wrappedCommand], {
@@ -424,7 +372,7 @@ describe('Socket Filtering Behavior', () => {
424372
})
425373

426374
it('should allow IPv6 socket creation', async () => {
427-
if (skipIfNotLinux() || skipIfNotAnt() || !filterPath) {
375+
if (skipIfNotLinux() || !filterPath) {
428376
return
429377
}
430378

@@ -433,6 +381,7 @@ describe('Socket Filtering Behavior', () => {
433381
const wrappedCommand = await wrapCommandWithSandboxLinux({
434382
command: testCommand,
435383
needsNetworkRestriction: false,
384+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
436385
})
437386

438387
const result = spawnSync('bash', ['-c', wrappedCommand], {
@@ -446,38 +395,39 @@ describe('Socket Filtering Behavior', () => {
446395
})
447396

448397
describe('Two-Stage Seccomp Application', () => {
449-
it('should allow network infrastructure to run before filter', async () => {
450-
if (skipIfNotLinux() || skipIfNotAnt()) {
398+
it('should include apply-seccomp in wrapped command when filesystem restricted', async () => {
399+
if (skipIfNotLinux()) {
451400
return
452401
}
453402

454403
if (checkLinuxDependencies().errors.length > 0) {
455404
return
456405
}
457406

458-
// This test verifies that the socat processes can start successfully
459-
// even though they use Unix sockets, because they run before the filter
460-
const testCommand = 'echo "test"'
461-
407+
// With filesystem restriction and no network, the no-socat branch at
408+
// linux-sandbox-utils.ts:1197 should apply seccomp directly.
409+
// Socat-before-seccomp ordering (the network-restricted branch) is
410+
// covered implicitly by integration.test.ts — if socat ran after
411+
// seccomp, its AF_UNIX socket would be blocked and every network
412+
// test there would fail.
462413
const wrappedCommand = await wrapCommandWithSandboxLinux({
463-
command: testCommand,
414+
command: 'echo "test"',
464415
needsNetworkRestriction: false,
416+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
465417
})
466418

467-
// Command should include both socat and the apply-seccomp binary
468-
expect(wrappedCommand).toContain('socat')
419+
expect(wrappedCommand).toContain('bwrap')
469420
expect(wrappedCommand).toContain('apply-seccomp')
470421

471-
// The socat should come before the apply-seccomp
472-
const socatIndex = wrappedCommand.indexOf('socat')
422+
const bwrapIndex = wrappedCommand.indexOf('bwrap')
473423
const seccompIndex = wrappedCommand.indexOf('apply-seccomp')
474-
expect(socatIndex).toBeGreaterThan(-1)
475-
expect(seccompIndex).toBeGreaterThan(-1)
476-
expect(socatIndex).toBeLessThan(seccompIndex)
424+
const commandIndex = wrappedCommand.indexOf('echo')
425+
expect(bwrapIndex).toBeLessThan(seccompIndex)
426+
expect(seccompIndex).toBeLessThan(commandIndex)
477427
})
478428

479429
it('should execute user command with filter applied', async () => {
480-
if (skipIfNotLinux() || skipIfNotAnt()) {
430+
if (skipIfNotLinux()) {
481431
return
482432
}
483433

@@ -491,6 +441,7 @@ describe('Two-Stage Seccomp Application', () => {
491441
const wrappedCommand = await wrapCommandWithSandboxLinux({
492442
command: testCommand,
493443
needsNetworkRestriction: false,
444+
writeConfig: TRIGGER_SANDBOX_WRITE_CONFIG,
494445
})
495446

496447
const result = spawnSync('bash', ['-c', wrappedCommand], {
@@ -546,30 +497,6 @@ describe('Sandbox Integration', () => {
546497
expect(wrappedCommand).toBeTruthy()
547498
expect(wrappedCommand).toContain('bwrap')
548499
})
549-
550-
it('should include seccomp for ANT users with dependencies', async () => {
551-
if (skipIfNotLinux()) {
552-
return
553-
}
554-
555-
if (checkLinuxDependencies().errors.length > 0) {
556-
return
557-
}
558-
559-
const testCommand = 'echo "test"'
560-
const wrappedCommand = await wrapCommandWithSandboxLinux({
561-
command: testCommand,
562-
needsNetworkRestriction: false,
563-
})
564-
565-
const isAnt = process.env.USER_TYPE === 'ant'
566-
567-
if (isAnt) {
568-
expect(wrappedCommand).toContain('apply-seccomp')
569-
} else {
570-
expect(wrappedCommand).not.toContain('apply-seccomp')
571-
}
572-
})
573500
})
574501

575502
describe('Error Handling', () => {

0 commit comments

Comments
 (0)