respdiff 0.2.0

Trait-based differential response analysis and probe learning for HTTP scanning.
Documentation
  • Coverage
  • 0%
    0 out of 46 items documented0 out of 0 items with examples
  • Size
  • Source code size: 65.07 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 4.72 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 33s Average build duration of successful builds.
  • all releases: 33s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • santhsecurity/respdiff
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • santhsecurity

respdiff

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, &current);

if diff.has_differences() {
    println!("Status changed: {}", diff.status_changed);
    println!("New headers: {:?}", diff.new_headers);
    println!("Body similarity: {:.2}", diff.body_similarity);
}

Why this exists

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.

Differential policies

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);

Probe learning

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);
}

Contributing

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.

License

MIT. Copyright 2026 CORUM COLLECTIVE LLC.

crates.io docs.rs