Trait-based differential response analysis and probe learning for HTTP scanning. It compares HTTP responses to find meaningful differences and automatically discovers injection gates from probe histories.
use std::time::Duration;
use respdiff::{ResponseSnapshot, compare_responses};
let baseline = ResponseSnapshot::new(
200,
vec![("Server", "nginx")],
"hello world"
).with_elapsed(Duration::from_millis(50));
let current = ResponseSnapshot::new(
500,
vec![("Server", "nginx"), ("X-Error", "1")],
"internal error"
).with_elapsed(Duration::from_millis(60));
let diff = compare_responses(&baseline, ¤t);
if diff.has_differences() {
println!("Status changed: {}", diff.status_changed);
println!("New headers: {:?}", diff.new_headers);
println!("Body similarity: {:.2}", diff.body_similarity);
}Scanners need to know if a payload actually changed the server's behavior. A raw text diff of two HTTP responses is useless because dynamic tokens, timestamps, and randomized content change on every request. respdiff understands HTTP semantics. It diffs headers intelligently, calculates body similarity using Jaccard index, and evaluates timing changes against configurable thresholds.
Configure the thresholds for what constitutes a meaningful difference.
use respdiff::{DiffPolicy, is_differential_match_with_policy};
let policy = DiffPolicy {
timing_threshold_ms: 200,
similarity_threshold: 0.85,
};
let is_match = is_differential_match_with_policy(&diff, &policy);The DifferentialLearner analyzes a history of observations to identify which input properties act as gates and which ones are injectable. It generates new variants based on successful shapes.
use std::time::Duration;
use respdiff::{DifferentialLearner, ProbeObservation};
let mut learner = DifferentialLearner::new().with_analyze_every(50);
learner.record(
[("action", "run"), ("payload", "test")],
ProbeObservation::matched(Duration::from_millis(5), ["code"])
);
let variants = learner.generate_variants(&["alert(1)"]);
for variant in variants {
println!("Try properties {:?} because {}", variant.properties, variant.reason);
}Pull requests are welcome. There is no such thing as a perfect crate. If you find a bug, a better API, or just a rough edge, open a PR. We review quickly.
MIT. Copyright 2026 CORUM COLLECTIVE LLC.