11import { describe , it , expect , beforeAll } from 'bun:test'
2+ import { spawnSync } from 'node:child_process'
23import { existsSync , statSync } from 'node:fs'
4+ import { tmpdir } from 'node:os'
35import { getPlatform } from '../../src/utils/platform.js'
46import { whichSync } from '../../src/utils/which.js'
57import {
@@ -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
2430describe ( 'Linux Sandbox Dependencies' , ( ) => {
@@ -239,42 +245,6 @@ describe('Apply Seccomp Binary', () => {
239245} )
240246
241247describe ( '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-
325269describe ( '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
448397describe ( '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
575502describe ( 'Error Handling' , ( ) => {
0 commit comments