use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
fn repo_root() -> PathBuf {
let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest
.parent()
.and_then(Path::parent)
.expect("sidecar crate should live two levels under the repo root")
.to_path_buf()
}
fn production_source_files(root: &Path) -> Vec<PathBuf> {
let mut out = Vec::new();
let crates_dir = root.join("crates");
let mut crate_dirs: Vec<PathBuf> = std::fs::read_dir(&crates_dir)
.expect("crates/ directory should exist")
.filter_map(|entry| entry.ok().map(|e| e.path()))
.filter(|p| p.is_dir())
.collect();
crate_dirs.sort();
for crate_dir in crate_dirs {
let src = crate_dir.join("src");
if src.is_dir() {
collect_rs(&src, root, &mut out);
}
}
out.sort();
out
}
fn collect_rs(dir: &Path, root: &Path, out: &mut Vec<PathBuf>) {
let mut entries: Vec<PathBuf> = std::fs::read_dir(dir)
.unwrap_or_else(|err| panic!("read_dir {dir:?}: {err}"))
.filter_map(|entry| entry.ok().map(|e| e.path()))
.collect();
entries.sort();
for path in entries {
if path.is_dir() {
if path.file_name().map(|n| n == "bin").unwrap_or(false) {
continue;
}
collect_rs(&path, root, out);
} else if path.extension().map(|e| e == "rs").unwrap_or(false) {
let rel = path
.strip_prefix(root)
.expect("source path under repo root")
.to_path_buf();
out.push(rel);
}
}
}
fn is_excluded_file(rel: &Path) -> bool {
let s = rel.to_string_lossy();
s.ends_with("build.rs")
|| s.ends_with("build_support.rs")
|| s.ends_with("v8_bridge_build.rs")
|| s == "crates/execution/src/benchmark.rs"
|| s.contains("/src/bin/")
}
fn strip_line_comment(line: &str) -> &str {
match line.find("//") {
Some(idx) => &line[..idx],
None => line,
}
}
struct CfgTestTracker {
pending_cfg_test: bool,
depth: u32,
}
impl CfgTestTracker {
fn new() -> Self {
Self {
pending_cfg_test: false,
depth: 0,
}
}
fn in_test(&mut self, raw: &str) -> bool {
let line = strip_line_comment(raw);
let trimmed = line.trim();
if self.depth > 0 {
self.depth += count_open(line);
self.depth = self.depth.saturating_sub(count_close(line));
return true;
}
if trimmed.starts_with("#[cfg(test)]") {
self.pending_cfg_test = true;
return false;
}
if self.pending_cfg_test {
if trimmed.is_empty() || trimmed.starts_with("#[") || trimmed.starts_with("//") {
return false;
}
self.pending_cfg_test = false;
if trimmed.starts_with("mod ")
|| trimmed.starts_with("pub mod ")
|| trimmed.starts_with("pub(crate) mod ")
|| trimmed.starts_with("pub(super) mod ")
{
self.depth = count_open(line).saturating_sub(count_close(line));
if self.depth == 0 {
}
return true;
}
return true;
}
false
}
}
fn count_open(s: &str) -> u32 {
s.bytes().filter(|&b| b == b'{').count() as u32
}
fn count_close(s: &str) -> u32 {
s.bytes().filter(|&b| b == b'}').count() as u32
}
struct BannedClass {
name: &'static str,
needles: &'static [&'static str],
allowlist: &'static [&'static str],
}
fn line_matches(line: &str, needles: &[&str]) -> bool {
needles.iter().any(|n| line.contains(n))
}
fn scan_class(root: &Path, files: &[PathBuf], class: &BannedClass) -> Vec<String> {
let allow: BTreeSet<&str> = class.allowlist.iter().copied().collect();
let mut violations = Vec::new();
for rel in files {
if is_excluded_file(rel) {
continue;
}
let rel_str = rel.to_string_lossy().replace('\\', "/");
let allowed = allow.contains(rel_str.as_str());
let abs = root.join(rel);
let content =
std::fs::read_to_string(&abs).unwrap_or_else(|err| panic!("read {abs:?}: {err}"));
let mut tracker = CfgTestTracker::new();
for (idx, raw) in content.lines().enumerate() {
let in_test = tracker.in_test(raw);
if allowed {
continue; }
if in_test {
continue;
}
let code = strip_line_comment(raw);
if line_matches(code, class.needles) {
violations.push(format!("{}:{}: {}", rel_str, idx + 1, raw.trim()));
}
}
}
violations
}
const FS_ALLOW: &[&str] = &[
"crates/sidecar/src/filesystem.rs",
"crates/sidecar/src/plugins/host_dir.rs",
"crates/sidecar/src/plugins/module_access.rs",
"crates/sidecar/src/stdio.rs",
"crates/sidecar/src/state.rs",
"crates/sidecar/src/vm.rs",
"crates/sidecar/src/service.rs",
"crates/sidecar/src/execution.rs",
"crates/execution/src/python.rs",
"crates/execution/src/wasm.rs",
"crates/execution/src/javascript.rs",
"crates/execution/src/node_import_cache.rs",
"crates/execution/src/runtime_support.rs",
];
const NET_ALLOW: &[&str] = &[
"crates/kernel/src/dns.rs",
"crates/kernel/src/socket_table.rs",
"crates/kernel/src/kernel.rs",
"crates/sidecar/src/execution.rs",
"crates/sidecar/src/state.rs",
"crates/sidecar/src/vm.rs",
"crates/sidecar/src/plugins/s3.rs",
"crates/sidecar/src/plugins/google_drive.rs",
"crates/sidecar/src/plugins/sandbox_agent.rs",
"crates/v8-runtime/src/embedded_runtime.rs",
"crates/execution/src/v8_runtime.rs",
"crates/secure-exec-client/src/transport.rs",
];
const PROCESS_ALLOW: &[&str] = &["crates/secure-exec-client/src/transport.rs"];
const ENV_ALLOW: &[&str] = &[
"crates/secure-exec-client/src/transport.rs",
"crates/execution/src/host_node.rs",
"crates/v8-runtime/src/bridge.rs",
"crates/sidecar/src/execution.rs",
"crates/sidecar/src/plugins/s3.rs",
];
fn fs_class() -> BannedClass {
BannedClass {
name: "fs",
needles: &[
"std::fs",
"tokio::fs",
"File::open",
"File::create",
"OpenOptions",
"openat",
],
allowlist: FS_ALLOW,
}
}
fn net_class() -> BannedClass {
BannedClass {
name: "net",
needles: &[
"std::net::",
"tokio::net::",
"reqwest::",
"reqwest ",
"hyper::",
"TcpStream::",
"TcpListener::bind",
"UdpSocket::bind",
"UnixStream::connect",
"UnixStream::pair",
"UnixListener::bind",
".to_socket_addrs(",
"std::os::unix::net",
],
allowlist: NET_ALLOW,
}
}
fn process_class() -> BannedClass {
BannedClass {
name: "process",
needles: &[
"std::process::Command",
"process::Command",
"tokio::process",
"Command::new",
"libc::fork",
"nix::unistd::fork",
],
allowlist: PROCESS_ALLOW,
}
}
fn env_class() -> BannedClass {
BannedClass {
name: "env",
needles: &[
"env::var(",
"env::var_os(",
"env::vars(",
"env::vars_os(",
"std::env::var",
],
allowlist: ENV_ALLOW,
}
}
fn assert_green(root: &Path, files: &[PathBuf], class: BannedClass) {
let violations = scan_class(root, files, &class);
assert!(
violations.is_empty(),
"\n\nChokepoint lint ({}) found {} host-API use(s) OUTSIDE the sanctioned \
allowlist.\nEither route the access through an existing chokepoint, or -- if this \
is a genuinely new sanctioned boundary -- add the file to the `{}` allowlist in \
crates/sidecar/tests/architecture_guards.rs with a justifying comment.\n\n{}\n",
class.name,
violations.len(),
match class.name {
"fs" => "FS_ALLOW",
"net" => "NET_ALLOW",
"process" => "PROCESS_ALLOW",
_ => "ENV_ALLOW",
},
violations.join("\n"),
);
}
#[test]
fn fs_access_confined_to_chokepoints() {
let root = repo_root();
let files = production_source_files(&root);
assert_green(&root, &files, fs_class());
}
#[test]
fn net_access_confined_to_chokepoints() {
let root = repo_root();
let files = production_source_files(&root);
assert_green(&root, &files, net_class());
}
#[test]
fn process_spawn_confined_to_chokepoints() {
let root = repo_root();
let files = production_source_files(&root);
assert_green(&root, &files, process_class());
}
#[test]
fn env_reads_confined_to_chokepoints() {
let root = repo_root();
let files = production_source_files(&root);
assert_green(&root, &files, env_class());
}
#[test]
fn lint_scans_real_sources_and_allowlist_paths_exist() {
let root = repo_root();
let files = production_source_files(&root);
assert!(
files.len() > 30,
"expected to scan many source files, found {}",
files.len()
);
let mut missing = Vec::new();
for class in [FS_ALLOW, NET_ALLOW, PROCESS_ALLOW, ENV_ALLOW] {
for rel in class {
if !root.join(rel).is_file() {
missing.push(rel.to_string());
}
}
}
missing.sort();
missing.dedup();
assert!(
missing.is_empty(),
"allowlist references files that no longer exist (clean them up): {missing:?}"
);
}
#[test]
fn no_secure_exec_crate_depends_on_agent_acp_session() {
let root = repo_root();
let crates_dir = root.join("crates");
let banned_dep_markers = ["agent", "acp", "session"];
let mut violations = Vec::new();
let mut crate_dirs: Vec<PathBuf> = std::fs::read_dir(&crates_dir)
.expect("crates/ exists")
.filter_map(|e| e.ok().map(|e| e.path()))
.filter(|p| p.is_dir())
.collect();
crate_dirs.sort();
for crate_dir in crate_dirs {
let manifest = crate_dir.join("Cargo.toml");
if !manifest.is_file() {
continue;
}
let text = std::fs::read_to_string(&manifest)
.unwrap_or_else(|err| panic!("read {manifest:?}: {err}"));
let mut in_deps = false;
for raw in text.lines() {
let line = raw.trim();
if line.starts_with('[') {
in_deps = line.contains("dependencies");
continue;
}
if !in_deps || line.is_empty() || line.starts_with('#') {
continue;
}
let key = line
.split(['=', ' ', '\t'])
.next()
.unwrap_or("")
.trim_matches('"')
.to_ascii_lowercase();
if key.is_empty() {
continue;
}
for marker in banned_dep_markers {
if key.contains(marker) {
violations.push(format!(
"{}: depends on banned crate `{}`",
manifest
.strip_prefix(&root)
.unwrap_or(&manifest)
.to_string_lossy(),
key
));
}
}
}
}
assert!(
violations.is_empty(),
"\n\nsecure-exec crates must not depend on agent/acp/session crates \
(Agent OS owns those). Offending dependencies:\n\n{}\n",
violations.join("\n")
);
}