@@ -44,26 +44,34 @@ describe("pathEscapePlugin", () => {
4444 expect ( result . isError ) . not . toBe ( true ) ;
4545 } ) ;
4646
47- test ( "blocks paths that escape cwd" , async ( ) => {
48- const plugin = pathEscapePlugin ( "/project" ) ;
49- const handler = plugin . middleware
50- ? plugin . middleware ( nextHandler )
51- : nextHandler ;
52- const result = await handler (
53- makeCall ( "read_file" , { path : "../secret.txt" } ) ,
54- new AbortController ( ) . signal ,
55- ) ;
56- expect ( result . isError ) . toBe ( true ) ;
57- expect ( result . content ) . toMatch ( / e s c a p e s w o r k i n g d i r e c t o r y / ) ;
58- } ) ;
47+ for ( const [ key , tool , value ] of [
48+ [ "path" , "read_file" , "../secret.txt" ] ,
49+ [ "path" , "read_file" , "/etc/passwd" ] ,
50+ [ "cwd" , "run_shell" , "../secret" ] ,
51+ [ "directory" , "list_dir" , "/etc" ] ,
52+ [ "source" , "copy" , "/etc/passwd" ] ,
53+ [ "filename" , "write_file" , "../secret.txt" ] ,
54+ ] as const ) {
55+ test ( `blocks escape via ${ key } key (${ tool } )` , async ( ) => {
56+ const plugin = pathEscapePlugin ( "/project" ) ;
57+ const handler = plugin . middleware
58+ ? plugin . middleware ( nextHandler )
59+ : nextHandler ;
60+ const result = await handler (
61+ makeCall ( tool , { [ key ] : value } ) ,
62+ new AbortController ( ) . signal ,
63+ ) ;
64+ expect ( result . isError ) . toBe ( true ) ;
65+ } ) ;
66+ }
5967
60- test ( "blocks absolute paths outside cwd " , async ( ) => {
68+ test ( "the block message tells the operator the path escapes the working directory " , async ( ) => {
6169 const plugin = pathEscapePlugin ( "/project" ) ;
6270 const handler = plugin . middleware
6371 ? plugin . middleware ( nextHandler )
6472 : nextHandler ;
6573 const result = await handler (
66- makeCall ( "read_file" , { path : "/etc/passwd " } ) ,
74+ makeCall ( "read_file" , { path : "../secret.txt " } ) ,
6775 new AbortController ( ) . signal ,
6876 ) ;
6977 expect ( result . isError ) . toBe ( true ) ;
@@ -82,58 +90,6 @@ describe("pathEscapePlugin", () => {
8290 expect ( result . isError ) . not . toBe ( true ) ;
8391 } ) ;
8492
85- test ( "blocks escape via cwd key" , async ( ) => {
86- const plugin = pathEscapePlugin ( "/project" ) ;
87- const handler = plugin . middleware
88- ? plugin . middleware ( nextHandler )
89- : nextHandler ;
90- const result = await handler (
91- makeCall ( "run_shell" , { cwd : "../secret" } ) ,
92- new AbortController ( ) . signal ,
93- ) ;
94- expect ( result . isError ) . toBe ( true ) ;
95- expect ( result . content ) . toMatch ( / e s c a p e s w o r k i n g d i r e c t o r y / ) ;
96- } ) ;
97-
98- test ( "blocks escape via directory key" , async ( ) => {
99- const plugin = pathEscapePlugin ( "/project" ) ;
100- const handler = plugin . middleware
101- ? plugin . middleware ( nextHandler )
102- : nextHandler ;
103- const result = await handler (
104- makeCall ( "list_dir" , { directory : "/etc" } ) ,
105- new AbortController ( ) . signal ,
106- ) ;
107- expect ( result . isError ) . toBe ( true ) ;
108- expect ( result . content ) . toMatch ( / e s c a p e s w o r k i n g d i r e c t o r y / ) ;
109- } ) ;
110-
111- test ( "blocks escape via source key" , async ( ) => {
112- const plugin = pathEscapePlugin ( "/project" ) ;
113- const handler = plugin . middleware
114- ? plugin . middleware ( nextHandler )
115- : nextHandler ;
116- const result = await handler (
117- makeCall ( "copy" , { source : "/etc/passwd" } ) ,
118- new AbortController ( ) . signal ,
119- ) ;
120- expect ( result . isError ) . toBe ( true ) ;
121- expect ( result . content ) . toMatch ( / e s c a p e s w o r k i n g d i r e c t o r y / ) ;
122- } ) ;
123-
124- test ( "blocks escape via filename key" , async ( ) => {
125- const plugin = pathEscapePlugin ( "/project" ) ;
126- const handler = plugin . middleware
127- ? plugin . middleware ( nextHandler )
128- : nextHandler ;
129- const result = await handler (
130- makeCall ( "write_file" , { filename : "../secret.txt" } ) ,
131- new AbortController ( ) . signal ,
132- ) ;
133- expect ( result . isError ) . toBe ( true ) ;
134- expect ( result . content ) . toMatch ( / e s c a p e s w o r k i n g d i r e c t o r y / ) ;
135- } ) ;
136-
13793 test ( "allowOutside passes outside paths through as absolute" , async ( ) => {
13894 const plugin = pathEscapePlugin ( "/project" , ( ) => [ ] , {
13995 allowOutside : true ,
0 commit comments