fix(tools): add 10 MB file size limit to file_read tool

Security fix: add 10 MB file size limit to file_read tool
This commit is contained in:
Argenis 2026-02-15 09:38:53 -05:00 committed by GitHub
parent 6899ad4b8e
commit 322f24fd63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -78,6 +78,30 @@ impl Tool for FileReadTool {
});
}
// Check file size AFTER canonicalization to prevent TOCTOU symlink bypass
const MAX_FILE_SIZE: u64 = 10 * 1024 * 1024;
match tokio::fs::metadata(&resolved_path).await {
Ok(meta) => {
if meta.len() > MAX_FILE_SIZE {
return Ok(ToolResult {
success: false,
output: String::new(),
error: Some(format!(
"File too large: {} bytes (limit: {MAX_FILE_SIZE} bytes)",
meta.len()
)),
});
}
}
Err(e) => {
return Ok(ToolResult {
success: false,
output: String::new(),
error: Some(format!("Failed to read file metadata: {e}")),
});
}
}
match tokio::fs::read_to_string(&resolved_path).await {
Ok(contents) => Ok(ToolResult {
success: true,
@ -255,4 +279,22 @@ mod tests {
let _ = tokio::fs::remove_dir_all(&root).await;
}
#[tokio::test]
async fn file_read_rejects_oversized_file() {
let dir = std::env::temp_dir().join("zeroclaw_test_file_read_large");
let _ = tokio::fs::remove_dir_all(&dir).await;
tokio::fs::create_dir_all(&dir).await.unwrap();
// Create a file just over 10 MB
let big = vec![b'x'; 10 * 1024 * 1024 + 1];
tokio::fs::write(dir.join("huge.bin"), &big).await.unwrap();
let tool = FileReadTool::new(test_security(dir.clone()));
let result = tool.execute(json!({"path": "huge.bin"})).await.unwrap();
assert!(!result.success);
assert!(result.error.as_ref().unwrap().contains("File too large"));
let _ = tokio::fs::remove_dir_all(&dir).await;
}
}