@@ -8,6 +8,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
88import { LinuxSandboxManager } from './LinuxSandboxManager.js' ;
99import type { SandboxRequest } from '../../services/sandboxManager.js' ;
1010import fs from 'node:fs' ;
11+ import path from 'node:path' ;
1112import * as shellUtils from '../../utils/shell-utils.js' ;
1213
1314vi . mock ( 'node:fs' , async ( ) => {
@@ -350,6 +351,61 @@ describe('LinuxSandboxManager', () => {
350351 const binds = bwrapArgs . filter ( ( a ) => a === workspace ) ;
351352 expect ( binds . length ) . toBe ( 2 ) ;
352353 } ) ;
354+
355+ it ( 'should bind the parent directory of a non-existent path' , async ( ) => {
356+ vi . mocked ( fs . existsSync ) . mockImplementation ( ( p ) => {
357+ if ( p === '/home/user/workspace/new-file.txt' ) return false ;
358+ return true ;
359+ } ) ;
360+
361+ const bwrapArgs = await getBwrapArgs ( {
362+ command : '__write' ,
363+ args : [ '/home/user/workspace/new-file.txt' ] ,
364+ cwd : workspace ,
365+ env : { } ,
366+ policy : {
367+ allowedPaths : [ '/home/user/workspace/new-file.txt' ] ,
368+ } ,
369+ } ) ;
370+
371+ const parentDir = '/home/user/workspace' ;
372+ const bindIndex = bwrapArgs . lastIndexOf ( parentDir ) ;
373+ expect ( bindIndex ) . not . toBe ( - 1 ) ;
374+ expect ( bwrapArgs [ bindIndex - 2 ] ) . toBe ( '--bind-try' ) ;
375+ } ) ;
376+ } ) ;
377+
378+ describe ( 'virtual commands' , ( ) => {
379+ it ( 'should translate __read to cat' , async ( ) => {
380+ const testFile = path . join ( workspace , 'file.txt' ) ;
381+ const bwrapArgs = await getBwrapArgs ( {
382+ command : '__read' ,
383+ args : [ testFile ] ,
384+ cwd : workspace ,
385+ env : { } ,
386+ } ) ;
387+
388+ // args are: [...bwrapBaseArgs, '--', '/bin/cat', '.../file.txt']
389+ expect ( bwrapArgs [ bwrapArgs . length - 2 ] ) . toBe ( '/bin/cat' ) ;
390+ expect ( bwrapArgs [ bwrapArgs . length - 1 ] ) . toBe ( testFile ) ;
391+ } ) ;
392+
393+ it ( 'should translate __write to sh -c cat' , async ( ) => {
394+ const testFile = path . join ( workspace , 'file.txt' ) ;
395+ const bwrapArgs = await getBwrapArgs ( {
396+ command : '__write' ,
397+ args : [ testFile ] ,
398+ cwd : workspace ,
399+ env : { } ,
400+ } ) ;
401+
402+ // args are: [...bwrapBaseArgs, '--', '/bin/sh', '-c', 'tee -- "$@" > /dev/null', '_', '.../file.txt']
403+ expect ( bwrapArgs [ bwrapArgs . length - 5 ] ) . toBe ( '/bin/sh' ) ;
404+ expect ( bwrapArgs [ bwrapArgs . length - 4 ] ) . toBe ( '-c' ) ;
405+ expect ( bwrapArgs [ bwrapArgs . length - 3 ] ) . toBe ( 'tee -- "$@" > /dev/null' ) ;
406+ expect ( bwrapArgs [ bwrapArgs . length - 2 ] ) . toBe ( '_' ) ;
407+ expect ( bwrapArgs [ bwrapArgs . length - 1 ] ) . toBe ( testFile ) ;
408+ } ) ;
353409 } ) ;
354410
355411 describe ( 'forbiddenPaths' , ( ) => {
0 commit comments