mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
* feat: add fuzzing targets for untrusted input parsers Add cargo-fuzz infrastructure with 5 fuzz targets exercising security-critical code paths: - fuzz_safety_sanitizer: Aho-Corasick + regex injection detection - fuzz_safety_validator: Input validation (length, encoding, patterns) - fuzz_leak_detector: Secret leak scanning (API keys, tokens) - fuzz_tool_params: Tool parameter JSON validation - fuzz_config_env: TOML/JSON config parsing Each target exercises real IronClaw business logic with invariant assertions. Includes corpus directories and setup documentation. Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: improve fuzz targets to exercise real IronClaw code paths - fuzz_config_env: exercise SafetyLayer end-to-end (sanitize, validate, policy check) instead of generic TOML/JSON parsing - fuzz_tool_params: add validate_tool_schema coverage alongside validate_tool_params - Add "fuzz" to workspace exclude in root Cargo.toml - Update README descriptions to match actual target behavior [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: replace redundant detect() call with meaningful invariant assertion Replace the double sanitize()+detect() call with an assertion that critical severity warnings always trigger content modification. Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: rewrite fuzz_config_env to exercise IronClaw safety code directly Replace SafetyLayer wrapper usage with direct Sanitizer, Validator, and LeakDetector instantiation and invocation. Adds meaningful consistency assertions (non-empty output, valid-means-no-errors, scan/clean agreement). Removes the config construction that was only exercising struct instantiation. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <[email protected]> --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
56 lines
2.1 KiB
Rust
56 lines
2.1 KiB
Rust
#![no_main]
|
|
use libfuzzer_sys::fuzz_target;
|
|
|
|
use ironclaw::safety::{LeakDetector, Sanitizer, Validator};
|
|
|
|
fuzz_target!(|data: &[u8]| {
|
|
if let Ok(input) = std::str::from_utf8(data) {
|
|
// Exercise Sanitizer: detect and neutralize prompt injection attempts.
|
|
let sanitizer = Sanitizer::new();
|
|
let sanitized = sanitizer.sanitize(input);
|
|
// The sanitized content must never be empty when input is non-empty,
|
|
// because sanitization wraps/escapes rather than deleting.
|
|
if !input.is_empty() {
|
|
assert!(
|
|
!sanitized.content.is_empty(),
|
|
"sanitize() produced empty content for non-empty input"
|
|
);
|
|
}
|
|
// If no modification occurred, content must equal input.
|
|
if !sanitized.was_modified {
|
|
assert_eq!(sanitized.content, input);
|
|
}
|
|
|
|
// Exercise Validator: input validation (length, encoding, patterns).
|
|
let validator = Validator::new();
|
|
let result = validator.validate(input);
|
|
// ValidationResult must always be well-formed: if valid, no errors.
|
|
if result.is_valid {
|
|
assert!(
|
|
result.errors.is_empty(),
|
|
"valid result should have no errors"
|
|
);
|
|
}
|
|
|
|
// Exercise LeakDetector: secret detection (API keys, tokens, etc.).
|
|
let detector = LeakDetector::new();
|
|
let scan = detector.scan(input);
|
|
// scan_and_clean must not panic and must return valid UTF-8.
|
|
let cleaned = detector.scan_and_clean(input);
|
|
if let Ok(ref clean_str) = cleaned {
|
|
// Cleaned output must never be longer than original + redaction markers.
|
|
// At minimum it should be valid UTF-8 (guaranteed by String type).
|
|
let _ = clean_str.len();
|
|
}
|
|
// If scan found no matches, scan_and_clean should return the input unchanged.
|
|
if scan.matches.is_empty() {
|
|
if let Ok(ref clean_str) = cleaned {
|
|
assert_eq!(
|
|
clean_str, input,
|
|
"scan_and_clean changed content despite no matches"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|