fix(ci): unblock dependabot dependency PR checks (#658)

This commit is contained in:
Will Sarg 2026-02-17 15:51:07 -05:00 committed by GitHub
parent 5be4fd9138
commit 42f1d40f1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 84 additions and 49 deletions

View file

@ -37,12 +37,16 @@ jobs:
include:
- name: no-default-features
args: --no-default-features
install_libudev: false
- name: all-features
args: --all-features
install_libudev: true
- name: hardware-only
args: --no-default-features --features hardware
install_libudev: false
- name: browser-native
args: --no-default-features --features browser-native
install_libudev: false
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
@ -54,6 +58,12 @@ jobs:
with:
key: features-${{ matrix.name }}
- name: Install Linux system dependencies for all-features
if: matrix.install_libudev
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libudev-dev pkg-config
- name: Check feature combination
run: cargo check --locked ${{ matrix.args }}

View file

@ -13,7 +13,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::sync::{Arc, Mutex};
use zeroclaw::agent::agent::Agent;
use zeroclaw::agent::dispatcher::{NativeToolDispatcher, XmlToolDispatcher, ToolDispatcher};
use zeroclaw::agent::dispatcher::{NativeToolDispatcher, ToolDispatcher, XmlToolDispatcher};
use zeroclaw::config::MemoryConfig;
use zeroclaw::memory;
use zeroclaw::memory::{Memory, MemoryCategory};

View file

@ -4,7 +4,7 @@
//! This module uses the pure-Rust `landlock` crate for filesystem access control.
#[cfg(all(feature = "sandbox-landlock", target_os = "linux"))]
use landlock::{AccessFS, Ruleset, RulesetCreated};
use landlock::{AccessFs, PathBeneath, PathFd, Ruleset, RulesetAttr, RulesetCreatedAttr};
use crate::security::traits::Sandbox;
use std::path::Path;
@ -26,9 +26,11 @@ impl LandlockSandbox {
/// Create a Landlock sandbox with a specific workspace directory
pub fn with_workspace(workspace_dir: Option<std::path::PathBuf>) -> std::io::Result<Self> {
// Test if Landlock is available by trying to create a minimal ruleset
let test_ruleset = Ruleset::new().set_access_fs(AccessFS::read_file | AccessFS::write_file);
let test_ruleset = Ruleset::default()
.handle_access(AccessFs::ReadFile | AccessFs::WriteFile)
.and_then(|ruleset| ruleset.create());
match test_ruleset.create() {
match test_ruleset {
Ok(_) => Ok(Self { workspace_dir }),
Err(e) => {
tracing::debug!("Landlock not available: {}", e);
@ -47,49 +49,75 @@ impl LandlockSandbox {
/// Apply Landlock restrictions to the current process
fn apply_restrictions(&self) -> std::io::Result<()> {
let mut ruleset = Ruleset::new().set_access_fs(
AccessFS::read_file
| AccessFS::write_file
| AccessFS::read_dir
| AccessFS::remove_dir
| AccessFS::remove_file
| AccessFS::make_char
| AccessFS::make_sock
| AccessFS::make_fifo
| AccessFS::make_block
| AccessFS::make_reg
| AccessFS::make_sym,
);
let mut ruleset = Ruleset::default()
.handle_access(
AccessFs::ReadFile
| AccessFs::WriteFile
| AccessFs::ReadDir
| AccessFs::RemoveDir
| AccessFs::RemoveFile
| AccessFs::MakeChar
| AccessFs::MakeSock
| AccessFs::MakeFifo
| AccessFs::MakeBlock
| AccessFs::MakeReg
| AccessFs::MakeSym,
)
.and_then(|ruleset| ruleset.create())
.map_err(|e| std::io::Error::other(e.to_string()))?;
// Allow workspace directory (read/write)
if let Some(ref workspace) = self.workspace_dir {
if workspace.exists() {
ruleset = ruleset.add_path(
workspace,
AccessFS::read_file | AccessFS::write_file | AccessFS::read_dir,
)?;
let workspace_fd =
PathFd::new(workspace).map_err(|e| std::io::Error::other(e.to_string()))?;
ruleset = ruleset
.add_rule(PathBeneath::new(
workspace_fd,
AccessFs::ReadFile | AccessFs::WriteFile | AccessFs::ReadDir,
))
.map_err(|e| std::io::Error::other(e.to_string()))?;
}
}
// Allow /tmp for general operations
ruleset = ruleset.add_path(
Path::new("/tmp"),
AccessFS::read_file | AccessFS::write_file,
)?;
let tmp_fd =
PathFd::new(Path::new("/tmp")).map_err(|e| std::io::Error::other(e.to_string()))?;
ruleset = ruleset
.add_rule(PathBeneath::new(
tmp_fd,
AccessFs::ReadFile | AccessFs::WriteFile,
))
.map_err(|e| std::io::Error::other(e.to_string()))?;
// Allow /usr and /bin for executing commands
ruleset = ruleset.add_path(Path::new("/usr"), AccessFS::read_file | AccessFS::read_dir)?;
ruleset = ruleset.add_path(Path::new("/bin"), AccessFS::read_file | AccessFS::read_dir)?;
let usr_fd =
PathFd::new(Path::new("/usr")).map_err(|e| std::io::Error::other(e.to_string()))?;
ruleset = ruleset
.add_rule(PathBeneath::new(
usr_fd,
AccessFs::ReadFile | AccessFs::ReadDir,
))
.map_err(|e| std::io::Error::other(e.to_string()))?;
let bin_fd =
PathFd::new(Path::new("/bin")).map_err(|e| std::io::Error::other(e.to_string()))?;
ruleset = ruleset
.add_rule(PathBeneath::new(
bin_fd,
AccessFs::ReadFile | AccessFs::ReadDir,
))
.map_err(|e| std::io::Error::other(e.to_string()))?;
// Apply the ruleset
match ruleset.create() {
match ruleset.restrict_self() {
Ok(_) => {
tracing::debug!("Landlock restrictions applied successfully");
Ok(())
}
Err(e) => {
tracing::warn!("Failed to apply Landlock restrictions: {}", e);
Err(std::io::Error::new(std::io::ErrorKind::Other, e))
Err(std::io::Error::other(e.to_string()))
}
}
}
@ -97,7 +125,7 @@ impl LandlockSandbox {
#[cfg(all(feature = "sandbox-landlock", target_os = "linux"))]
impl Sandbox for LandlockSandbox {
fn wrap_command(&self, cmd: &mut std::process::Command) -> std::io::Result<()> {
fn wrap_command(&self, _cmd: &mut std::process::Command) -> std::io::Result<()> {
// Apply Landlock restrictions before executing the command
// Note: This affects the current process, not the child process
// Child processes inherit the Landlock restrictions
@ -106,9 +134,9 @@ impl Sandbox for LandlockSandbox {
fn is_available(&self) -> bool {
// Try to create a minimal ruleset to verify availability
Ruleset::new()
.set_access_fs(AccessFS::read_file)
.create()
Ruleset::default()
.handle_access(AccessFs::ReadFile)
.and_then(|ruleset| ruleset.create())
.is_ok()
}

View file

@ -69,8 +69,9 @@ impl ScreenshotTool {
);
// Reject filenames with shell-breaking characters to prevent injection in sh -c
const SHELL_UNSAFE: &[char] =
&['\'', '"', '`', '$', '\\', ';', '|', '&', '\n', '\0', '(', ')'];
const SHELL_UNSAFE: &[char] = &[
'\'', '"', '`', '$', '\\', ';', '|', '&', '\n', '\0', '(', ')',
];
if safe_name.contains(SHELL_UNSAFE) {
return Ok(ToolResult {
success: false,
@ -307,10 +308,7 @@ mod tests {
.await
.unwrap();
assert!(!result.success);
assert!(result
.error
.unwrap()
.contains("unsafe for shell execution"));
assert!(result.error.unwrap().contains("unsafe for shell execution"));
}
#[test]

View file

@ -107,7 +107,12 @@ struct CountingTool {
impl CountingTool {
fn new() -> (Self, Arc<Mutex<usize>>) {
let count = Arc::new(Mutex::new(0));
(Self { count: count.clone() }, count)
(
Self {
count: count.clone(),
},
count,
)
}
}
@ -163,10 +168,7 @@ fn tool_response(calls: Vec<ToolCall>) -> ChatResponse {
}
}
fn build_agent(
provider: Box<dyn Provider>,
tools: Vec<Box<dyn Tool>>,
) -> Agent {
fn build_agent(provider: Box<dyn Provider>, tools: Vec<Box<dyn Tool>>) -> Agent {
Agent::builder()
.provider(provider)
.tools(tools)
@ -178,10 +180,7 @@ fn build_agent(
.unwrap()
}
fn build_agent_xml(
provider: Box<dyn Provider>,
tools: Vec<Box<dyn Tool>>,
) -> Agent {
fn build_agent_xml(provider: Box<dyn Provider>, tools: Vec<Box<dyn Tool>>) -> Agent {
Agent::builder()
.provider(provider)
.tools(tools)