Skip to content

Commit 7e0fc0c

Browse files
committed
fix(engine): compile exec runner on windows
Include the exec runner on Windows (cfg + re-export) and treat WorkspaceWrite network_access as a bool so nightly MSVC builds. Co-authored-by: Mathis <echobt@users.noreply.github.com>
1 parent c965820 commit 7e0fc0c

3 files changed

Lines changed: 69 additions & 14 deletions

File tree

src/cortex-engine/src/exec/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
mod environment;
44
mod output;
55
mod policy;
6-
#[cfg(any(target_os = "linux", target_os = "macos"))]
6+
// Process-group teardown is Unix-only; the runner itself is required on Windows
7+
// so local_shell / plugin exec still compile (job-object isolation is separate).
8+
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
79
mod runner;
810
pub use environment::{build_safe_environment, is_sensitive_env_name};
911

1012
pub use output::OutputCapture;
13+
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1114
pub use runner::{
1215
ExecOptions, ExecOutput, OutputChunk, execute_command, execute_command_streaming,
1316
};

src/cortex-engine/src/exec/policy.rs

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,39 @@ use super::ExecOptions;
33
use crate::error::{CortexError, Result};
44
use crate::sandbox::{SandboxPolicyType, SandboxRunner, SandboxedCommand, WritableRoot};
55
use cortex_protocol::SandboxPolicy;
6+
use std::path::Path;
67

78
pub(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

4041
async 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+
}

src/cortex-engine/src/exec/runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ pub async fn execute_command_streaming(
211211
Ok(output)
212212
}
213213

214-
#[cfg(test)]
214+
#[cfg(all(test, unix))]
215215
mod tests {
216216
use super::*;
217217
#[tokio::test]

0 commit comments

Comments
 (0)