Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@
**Vulnerability:** The `verify_github_sig` function in `apps/server/src/infra_routes.rs` verified GitHub webhook signatures using standard string comparison `expected.eq_ignore_ascii_case(hex_sig)`.
**Learning:** String comparison functions exit early as soon as a character mismatch is found. In a cryptographic context, this variable response time leaks information and allows an attacker to perform a timing attack to forge a valid HMAC signature by guessing it byte by byte.
**Prevention:** Always use a constant-time comparison library (like `hmac`'s `verify_slice()`) to compare cryptographic hashes, secrets, and signatures to prevent side-channel timing attacks. Avoid custom implementations of standard cryptographic algorithms.
## 2026-11-07 - [Strict Binary Enforcement in Shell Agent]
**Vulnerability:** Shell agent validation only matched joined strings against the `BLOCKED_TOKENS` blocklist. If a blocked command token did not match whitespace boundaries correctly within the overall command string (e.g. `npm run rm` rather than `rm `), restricted binaries like `rm` could bypass validation.
**Learning:** Checking a single joined command string for blocked tokens is insufficient because word boundaries might not line up cleanly when parsing complex subcommands. Multi-word checks or partial substring blocks require both full-string substring checks AND exact-word token matching.
**Prevention:** Always perform tokenization and exact matching on word boundaries in addition to substring blocking.
16 changes: 16 additions & 0 deletions crates/agent/src/tools/workdir_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ fn validate_command(raw: &str) -> std::result::Result<Vec<String>, String> {
return Err(format!("token interdit dans la commande : {bad}"));
}
}

for part in &parts {
let p_lower = part.to_ascii_lowercase();
if p_lower == "rm" || p_lower == "sudo" || p_lower == "chmod" || p_lower == "chown" {
return Err(format!("token exact interdit : {part}"));
}
}

let bin = parts[0].as_str();
let bin_base = Path::new(bin)
.file_name()
Expand Down Expand Up @@ -355,6 +363,14 @@ mod tests {
assert!(validate_command("npm run \"s\"udo").is_err());
assert!(validate_command("cat \"..\"/\"..\"/etc/passwd").is_err());
}

#[test]
fn blocks_exact_match_sensitive_binaries() {
assert!(validate_command("npm run rm").is_err());
assert!(validate_command("npm run sudo").is_err());
assert!(validate_command("npm run chmod").is_err());
assert!(validate_command("npm run chown").is_err());
}
}

/// Tue le groupe de processus (npm et ses scripts enfants) si le futur est abandonné.
Expand Down
Loading