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
5 changes: 5 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@
**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-11 - [Bypass Command Parsing - rm]
**Vulnerability:** The `validate_command` function in `crates/agent/src/tools/workdir_cmd.rs` used a trailing space in the `BLOCKED_TOKENS` list for `rm ` and `rm\t` to prevent matching prefixes like `arm` or `chmod`. This logic, however, did not block exact uses of `rm` at the end of a command string, such as `npm run rm`. It also relied primarily on the joined command string without checking the individual parsed tokens for exact matches of these sensitive binaries.
**Learning:** Checking for substrings against joined command strings can be bypassed if the restricted token happens at the end of the string where a space is not appended, or if the tokenizer fails to match exact words.
**Prevention:** Validation for string tokens should run not just against the joined command but also check for exact token matches over the tokenized arguments (e.g. iterate over tokens and verify `token.to_ascii_lowercase() == "rm"`).
7 changes: 7 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,12 @@ 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" {
return Err(format!("token interdit dans la commande : rm"));
}
}
let bin = parts[0].as_str();
let bin_base = Path::new(bin)
.file_name()
Expand Down Expand Up @@ -354,6 +360,7 @@ mod tests {
fn blocks_obfuscated_commands() {
assert!(validate_command("npm run \"s\"udo").is_err());
assert!(validate_command("cat \"..\"/\"..\"/etc/passwd").is_err());
assert!(validate_command("npm run rm").is_err());
}
}

Expand Down
Loading