parlov-elicit
Elicitation engine for parlov. Given a target endpoint and operator context, generates a plan of ProbeSpecs designed to trigger specific server-side differentials that reveal resource existence.
Overview
The engine codifies the elicitation playbook as 32 composable strategies across three detection vectors. Each strategy targets a different layer of the HTTP pipeline — content negotiation, conditional headers, cache validation, auth, payload validation, rate limiting — and produces probe definitions with Technique metadata that the binary feeds into its execution loops.
Usage
use parlov_elicit::{generate_plan, RiskLevel, ScanContext};
use http::HeaderMap;
let ctx = ScanContext {
target: "https://api.example.com/users/{id}".to_string(),
baseline_id: "1001".to_string(),
probe_id: "9999".to_string(),
headers: HeaderMap::new(),
max_risk: RiskLevel::Safe,
known_duplicate: None,
state_field: None,
alt_credential: None,
};
let plan = generate_plan(&ctx);
Strategies
Status Code Diff (Vector::StatusCodeDiff)
| # |
ID |
Risk |
Methods |
Prereq |
| 1 |
accept-elicit |
Safe |
GET, HEAD |
— |
| 2 |
if-none-match-elicit |
Safe |
GET, HEAD |
— |
| 3 |
trailing-slash-elicit |
Safe |
GET, HEAD |
— |
| 4 |
case-normalize-elicit |
Safe |
GET, HEAD |
— |
| 5 |
long-uri-elicit |
Safe |
GET, HEAD |
— |
| 6 |
auth-strip-elicit |
Safe |
GET, HEAD |
Authorization header |
| 7 |
low-privilege-elicit |
Safe |
GET, HEAD |
Authorization header |
| 8 |
scope-manipulation-elicit |
Safe |
GET, HEAD |
alt_credential |
| 9 |
rate-limit-headers-elicit |
Safe |
GET, HEAD |
— |
| 10 |
content-type-elicit |
MethodDestructive |
POST, PUT, PATCH |
— |
| 11 |
if-match-elicit |
MethodDestructive |
PUT, PATCH, DELETE |
— |
| 12 |
empty-body-elicit |
MethodDestructive |
POST, PUT, PATCH |
— |
| 13 |
oversized-body-elicit |
MethodDestructive |
POST, PUT, PATCH |
— |
| 14 |
state-transition-elicit |
MethodDestructive |
PATCH, PUT |
state_field |
| 15 |
uniqueness-elicit |
OperationDestructive |
POST, PUT |
known_duplicate |
| 16 |
dependency-delete-elicit |
OperationDestructive |
DELETE |
— |
| 17 |
rate-limit-burst-elicit |
OperationDestructive |
GET, HEAD |
— |
Cache Probing (Vector::CacheProbing)
| # |
ID |
Risk |
Methods |
Prereq |
| 18 |
cp-if-none-match |
Safe |
GET, HEAD |
— |
| 19 |
cp-if-modified-since |
Safe |
GET, HEAD |
— |
| 20 |
cp-if-match |
Safe |
GET, HEAD |
— |
| 21 |
cp-if-unmodified-since |
Safe |
GET, HEAD |
— |
| 22 |
cp-range |
Safe |
GET |
— |
| 23 |
cp-range-unsatisfiable |
Safe |
GET |
— |
| 24 |
cp-if-range |
Safe |
GET |
— |
| 25 |
cp-accept |
Safe |
GET, HEAD |
— |
Error Message Granularity (Vector::ErrorMessageGranularity)
| # |
ID |
Risk |
Methods |
Prereq |
| 26 |
emg-bola |
Safe |
GET |
— |
| 27 |
emg-query-validation |
Safe |
GET |
— |
| 28 |
emg-app-vs-server-404 |
Safe |
GET |
— |
| 29 |
emg-schema-validation-patch |
MethodDestructive |
PATCH |
— |
| 30 |
emg-schema-validation-put |
MethodDestructive |
PUT |
— |
| 31 |
emg-state-conflict |
MethodDestructive |
POST |
— |
| 32 |
emg-fk-violation |
MethodDestructive |
DELETE |
— |
Design
- Pure computation — no I/O, no async. The binary owns the async boundary.
- Strategy as trait — adding a strategy is one file + one registry line.
- Three detection vectors —
StatusCodeDiff (status code differentials), CacheProbing (cache-conditional header responses), and ErrorMessageGranularity (response body differentials). Strategies are organized by vector under existence/status_code_diff/, existence/cache_probing/, and existence/error_message_granularity/.
Technique metadata — every ProbeSpec carries technique context (id, name, vector, normative strength) that flows through execution into analysis. Signal extraction is unconditional.
ProbeSpec variants drive dispatch in the binary: Pair → adaptive loop, Burst → volume loop, HeaderDiff → single-request header comparison.
RiskLevel uses Ord — generate_plan filters with risk() <= ctx.max_risk.