parlov 0.8.0

HTTP oracle detection tool — systematic probing for RFC-compliant information leakage.
Documentation
# parlov

HTTP oracle detection tool — systematic probing for RFC-compliant information leakage.

HTTP servers that faithfully implement RFC 9110 often leak protected internal state through deterministic differences in status codes, cache-conditional responses, and response metadata. parlov detects those differential signals, scores confidence with per-signal normative weighting, and reports whether an application is vulnerable to oracle-based enumeration.

```bash
cargo install parlov
```

## usage

### manual probe (`existence`) — deprecated

> Deprecated since 0.8.0. Use `parlov scan --strategy <id>` for single-strategy runs; the `existence` subcommand is retained for backward compatibility.

```bash
# GET existence check
parlov existence \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --method GET

# POST registration enumeration
parlov existence \
  --target "https://api.example.com/register" \
  --baseline-id "alice@corp.com" \
  --method POST \
  --body '{"email": "{id}", "password": "test123"}'

# HEAD — lightweight, no response body
parlov existence \
  --target "https://api.example.com/users/{id}/avatar" \
  --baseline-id "1001" \
  --method HEAD

# with auth header
parlov existence \
  --target "https://api.example.com/projects/{id}" \
  --baseline-id "proj-abc" \
  --method GET \
  --header "Authorization: Bearer eyJhbG..."
```

### automated scan (`scan`)

```bash
# default: all vectors, safe risk
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001"

# specific vector with risk ceiling
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --vector cache-probing:safe

# mixed risk per vector
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --vector status-code-diff:method-destructive \
  --vector cache-probing:safe \
  --vector error-message-granularity:safe

# specific vector with risk ceiling
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --vector redirect-diff:safe

# specific strategy
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --strategy cp-if-none-match

# SARIF output for CI integration
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --format sarif

# reproducible curl commands per finding (Authorization not redacted)
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --header "Authorization: Bearer eyJhbG..." \
  --repro

# include filtered headers + body samples in each finding
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --verbose

# run every strategy regardless of interim confidence
parlov scan \
  --target "https://api.example.com/users/{id}" \
  --baseline-id "1001" \
  --exhaustive
```

39 strategies across four detection vectors (16 status-code-diff + 8 cache-probing + 7 error-message-granularity + 8 redirect-diff). Each scan also walks a Producer/Consumer DAG to emit Phase-2 chained probes informed by Phase-1 observations (`Location` redirects, `ETag` validators, harvested resource IDs, `Problem-Details` envelopes, `Content-Type` negotiation, auth challenges). Each finding includes a confidence score, impact class, severity, and deterministic finding ID for cross-run deduplication; the run as a whole carries an `EndpointVerdict` envelope with posterior probability, stop reason, and observability status.

## options

### global

| Flag | Description |
|------|-------------|
| `--format` | Output format: `table` (default), `json`, `sarif` |

### `existence` subcommand

| Flag | Description |
|------|-------------|
| `--target` | URL template with `{id}` placeholder |
| `--baseline-id` | Resource ID known to exist |
| `--probe-id` | Resource ID to test (defaults to random UUIDv4) |
| `--method` | HTTP method (defaults to GET) |
| `--header` | Request header in `Name: Value` format (repeatable) |
| `--body` | Body template with `{id}` placeholder |

### `scan` subcommand

| Flag | Description |
|------|-------------|
| `--target` | URL template with `{id}` placeholder |
| `--baseline-id` | Resource ID known to exist |
| `--probe-id` | Resource ID to test (defaults to random UUIDv4) |
| `--body` | Body template with `{id}` placeholder (required when the API identifies resources via body) |
| `--header` | Request header in `Name: Value` format (repeatable) |
| `--vector` | Detection vector with optional risk ceiling (repeatable) |
| `--risk` | Global risk ceiling for all vectors (mutually exclusive with `--vector`) |
| `--strategy` | Run specific strategy by ID (repeatable, mutually exclusive with `--risk` and `--vector`) |
| `--alt-credential` | Alternative credential header for scope manipulation |
| `--known-duplicate` | Known duplicate value for uniqueness strategies (`field=value`) |
| `--state-field` | State field name for state transition strategies (`field=value`) |
| `--exhaustive` | Run all strategies regardless of interim confidence; records the first-confirming strategy |
| `--repro` | Emit reproducible `curl` commands for each non-`NotPresent` finding (headers NOT redacted) |
| `--verbose` | Include filtered request/response headers and 256-byte body samples in each finding (headers NOT redacted) |

## exit codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Runtime error |

## license

MIT OR Apache-2.0