@@ -3,38 +3,39 @@ use super::ExecOptions;
33use crate :: error:: { CortexError , Result } ;
44use crate :: sandbox:: { SandboxPolicyType , SandboxRunner , SandboxedCommand , WritableRoot } ;
55use cortex_protocol:: SandboxPolicy ;
6+ use std:: path:: Path ;
67
78pub ( super ) async fn prepare ( command : & [ String ] , options : & ExecOptions ) -> Result < SandboxedCommand > {
89 evaluate ( command, options. approval_granted ) . await ?;
9- let policy = match & options. sandbox_policy {
10+ let policy = mapped_sandbox_policy ( & options. sandbox_policy , & options. cwd ) ?;
11+ SandboxRunner :: new ( ) . prepare ( command, & policy, & options. cwd )
12+ }
13+
14+ fn mapped_sandbox_policy ( policy : & SandboxPolicy , cwd : & Path ) -> Result < SandboxPolicyType > {
15+ Ok ( match policy {
1016 SandboxPolicy :: DangerFullAccess => SandboxPolicyType :: DangerFullAccess ,
1117 SandboxPolicy :: ReadOnly => SandboxPolicyType :: Custom {
1218 writable_roots : Vec :: new ( ) ,
1319 network_access : false ,
1420 allow_read_outside_workspace : true ,
1521 } ,
16- SandboxPolicy :: WorkspaceWrite {
17- writable_roots,
18- network_access,
19- ..
20- } => {
22+ SandboxPolicy :: WorkspaceWrite { writable_roots, .. } => {
2123 // Never infer permission from HOME caches, TMPDIR, or /tmp.
22- let mut roots = vec ! [ WritableRoot :: with_standard_protections(
23- options. cwd. canonicalize( ) ?,
24- ) ] ;
24+ let mut roots = vec ! [ WritableRoot :: with_standard_protections( cwd. canonicalize( ) ?) ] ;
2525 for path in writable_roots {
2626 roots. push ( WritableRoot :: with_standard_protections (
2727 path. canonicalize ( ) ?,
2828 ) ) ;
2929 }
3030 SandboxPolicyType :: Custom {
3131 writable_roots : roots,
32- network_access : * network_access,
32+ // `network_access` is a `bool`. Do not dereference it: rustc match
33+ // ergonomics bind the Copy field as `bool` on Windows nightly (E0614).
34+ network_access : policy. has_full_network_access ( ) ,
3335 allow_read_outside_workspace : true ,
3436 }
3537 }
36- } ;
37- SandboxRunner :: new ( ) . prepare ( command, & policy, & options. cwd )
38+ } )
3839}
3940
4041async fn evaluate ( command : & [ String ] , approved : bool ) -> Result < ( ) > {
@@ -52,3 +53,54 @@ async fn evaluate(command: &[String], approved: bool) -> Result<()> {
5253 ) ) ,
5354 }
5455}
56+
57+ #[ cfg( test) ]
58+ mod tests {
59+ use super :: * ;
60+
61+ fn workspace_write ( network_access : bool ) -> SandboxPolicy {
62+ SandboxPolicy :: WorkspaceWrite {
63+ writable_roots : vec ! [ ] ,
64+ network_access,
65+ exclude_tmpdir_env_var : false ,
66+ exclude_slash_tmp : false ,
67+ }
68+ }
69+
70+ #[ test]
71+ fn workspace_write_network_access_is_copied_as_bool ( ) {
72+ let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
73+ let cwd = dir. path ( ) ;
74+
75+ let enabled = mapped_sandbox_policy ( & workspace_write ( true ) , cwd) . unwrap ( ) ;
76+ assert ! ( matches!(
77+ enabled,
78+ SandboxPolicyType :: Custom {
79+ network_access: true ,
80+ ..
81+ }
82+ ) ) ;
83+
84+ let disabled = mapped_sandbox_policy ( & workspace_write ( false ) , cwd) . unwrap ( ) ;
85+ assert ! ( matches!(
86+ disabled,
87+ SandboxPolicyType :: Custom {
88+ network_access: false ,
89+ ..
90+ }
91+ ) ) ;
92+ }
93+
94+ #[ test]
95+ fn read_only_disables_network_access ( ) {
96+ let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
97+ let policy = mapped_sandbox_policy ( & SandboxPolicy :: ReadOnly , dir. path ( ) ) . unwrap ( ) ;
98+ assert ! ( matches!(
99+ policy,
100+ SandboxPolicyType :: Custom {
101+ network_access: false ,
102+ ..
103+ }
104+ ) ) ;
105+ }
106+ }
0 commit comments