📊 Reports
OpenDoor can write scan results in several formats.
Reports are configured with:
opendoor --host https://example.com --reports std,json,html
Use a custom output directory:
opendoor --host https://example.com --reports json,sqlite --reports-dir ./reports
Supported formats
| Format | Purpose |
|---|---|
std |
Terminal output |
txt |
Plain text output |
json |
Machine-readable output |
csv |
Spreadsheet-friendly output |
html |
Human-readable report |
sqlite |
Structured local database for post-processing |
sarif |
SARIF 2.1.0 output for CI/CD code scanning |
Use the exact formats shown by:
opendoor --help
because available report plugins can vary by build.
Terminal output
opendoor --host https://example.com --reports std
Use std for interactive work. std is the terminal summary output. It is always appended to scan reports, so users normally do not need to include it explicitly. Use --reports std only when you want terminal summary output without file reports.
The terminal summary includes all result buckets.
Text
opendoor --host https://example.com --reports txt
Use txt when you want one plain text file per result bucket.
When directory requests exhaust the configured timeout and retry budget without any HTTP response, OpenDoor writes those consumed-but-unverified paths to transport_failed.txt. These lines are not findings; they show wordlist entries that may need a later rescan after a temporary network outage or route failure. Subdomain no-response candidates are not written to this file because they are normal enumeration misses.
Header-bypass candidates include evidence in the bypass report lines, for example:
https://example.com/admin - 200 - 90B | bypass=header, header=X-Original-URL, value=/admin, 403->200
JSON
opendoor --host https://example.com --reports json
Use JSON for automation, pipelines, post-processing, and CI/CD artifact uploads.
JSON preserves detailed report_items metadata, including WAF, fingerprint, calibration, header-bypass, redirect classification, secret, stacktrace, shadow, endpoint and openredirect fields.
When transport-exhausted directory entries exist, JSON also preserves them in the top-level transport_failed list.
CSV
opendoor --host https://example.com --reports csv
Use CSV for spreadsheets, simple data analysis, and CI artifacts that need stable columns.
Header Injection Bypass columns:
| Column | Meaning |
|---|---|
bypass |
Bypass type, currently header |
bypass_header |
Header that produced the candidate |
bypass_value |
Header value used for the probe |
bypass_from_code |
Original blocked status code |
bypass_to_code |
Resulting status code |
Shadow Copy Detection columns:
| Column | Meaning |
|---|---|
shadow |
Shadow finding type |
shadow_confidence |
Confidence score for the exposed copy |
shadow_reason |
Detection reason, for example content_match |
shadow_base_url |
Original confirmed file used as the probe base |
shadow_variant |
Matched suffix or template variant such as .bak, .old, ~, or tpl:{path}2.{ext} |
shadow_similarity |
Similarity score used by the detector |
Endpoint detection is stored through the shared structured finding columns (finding_type, finding_severity, finding_reason, finding_confidence, finding_source, and finding_evidence). The nested JSON/HTML/SARIF metadata also preserves endpoint_detection with bounded endpoint samples.
Open Redirect Verification columns:
| Column | Meaning |
|---|---|
openredirect |
Finding type, currently open_redirect |
openredirect_confidence |
Confidence score for the confirmed redirect |
openredirect_parameter |
Redirect-like query parameter that accepted the marker payload |
openredirect_payload |
Controlled marker payload used for verification |
openredirect_variant |
Payload variant name |
openredirect_location |
Confirmed Location header value |
openredirect_source_url |
Original discovered URL used as the probe base |
Differential report comparison
--diff compares two existing OpenDoor reports and shows how the discovered surface changed between a previous and a current state. It is a local report-comparison command, not a scan mode against the target.
Supported input pairs:
| Input pair | Supported | Notes |
|---|---|---|
old.sqlite:new.sqlite |
yes | Preferred for structured local report comparison |
old.json:new.json |
yes | Useful for portable CI artifacts |
old.sqlite:new.json |
no | Mixed formats are rejected |
| TXT / CSV / HTML / SARIF | no | These are output/reporting formats, not diff inputs |
Example:
opendoor --diff baseline.sqlite:current.sqlite --reports std,json --reports-dir ./diff
The terminal output includes:
addedfindings that exist only in the current report;removedfindings that exist only in the previous report;changedfindings where the same endpoint changed status, bucket, size or redirect location;unchangedcount for stable findings.
When JSON output is requested, OpenDoor writes opendoor-diff.json. The JSON structure is deterministic and contains summary, added, removed and changed keys.
Validation is strict by design. Diff mode accepts exactly two same-format reports. Missing files, directories, invalid JSON, invalid SQLite files, unsupported schemas and malformed --diff values return graceful errors. Diff mode does not send HTTP requests, does not require --host, does not run the scan engine and does not store comparison history.
SARIF
opendoor --host https://example.com --reports sarif
Use SARIF when OpenDoor findings should be consumed by CI/CD security tooling such as GitHub Code Scanning.
OpenDoor writes SARIF 2.1.0 files with one run per generated report. Result buckets are mapped to stable rule ids such as:
| Bucket | SARIF rule id | Level |
|---|---|---|
success |
opendoor.finding.success |
warning |
indexof |
opendoor.finding.indexof |
warning |
auth |
opendoor.finding.auth |
warning |
forbidden |
opendoor.finding.forbidden |
note |
blocked |
opendoor.finding.blocked |
warning |
bypass |
opendoor.finding.bypass |
warning |
shadow |
opendoor.finding.shadow |
warning |
openredirect |
opendoor.finding.openredirect |
error |
endpoint |
opendoor.finding.endpoint |
note |
| fingerprint metadata | opendoor.fingerprint.detected |
note |
SARIF result properties preserve OpenDoor-specific evidence: target, URL, bucket, status code, response size, WAF metadata, bypass metadata, redirect classification metadata, secret/stacktrace/shadow/endpoint/openredirect metadata and fingerprint metadata.
Example GitHub Code Scanning upload:
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v6
- name: Run OpenDoor
run: |
opendoor \
--host https://example.com \
--reports sarif,json \
--reports-dir ./reports
- name: Upload OpenDoor SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: reports/example.com/example.com.sarif
category: opendoor
HTML
opendoor --host https://example.com --reports html
Use HTML for a readable standalone report.
HTML preserves detailed report_items metadata, including header-bypass, redirect classification, secret, stacktrace, shadow, endpoint and openredirect evidence.
SQLite
opendoor --host https://example.com --reports sqlite
Use SQLite when you want structured local analysis, later filtering, or integration with other tools.
SQLite is useful for:
- large scans;
- batch scans;
- CI artifacts;
- recurring exposure checks;
- historical comparison.
SQLite persists Header Injection Bypass, Redirect Classification, Shadow Copy Detection and Open Redirect Verification metadata in nullable item columns. Endpoint detections use the shared structured finding columns and preserve bounded evidence such as endpoint family, confidence, source signal and endpoint samples.
Header Injection Bypass columns:
| Column | Meaning |
|---|---|
bypass |
Bypass type |
bypass_header |
Header that produced the candidate |
bypass_value |
Header value used for the probe |
bypass_from_code |
Original blocked status code |
bypass_to_code |
Resulting status code |
Shadow Copy Detection columns:
| Column | Meaning |
|---|---|
shadow |
Shadow finding type |
shadow_confidence |
Confidence score for the exposed copy |
shadow_reason |
Detection reason, for example content_match |
shadow_base_url |
Original confirmed file used as the probe base |
shadow_variant |
Matched suffix or template variant such as .bak, .old, ~, or tpl:{path}2.{ext} |
shadow_similarity |
Similarity score used by the detector |
Open Redirect Verification columns:
| Column | Meaning |
|---|---|
openredirect |
Finding type |
openredirect_confidence |
Confidence score |
openredirect_parameter |
Redirect-like query parameter that accepted the marker payload |
openredirect_payload |
Controlled marker payload used for verification |
openredirect_variant |
Payload variant name |
openredirect_location |
Confirmed Location header value |
openredirect_source_url |
Original discovered URL used as the probe base |
Multiple reports
opendoor \
--host https://example.com \
--reports std,json,html,sqlite,csv,sarif \
--reports-dir ./reports
This is useful when one scan needs both human-readable and machine-readable output.
Shadow-copy evidence
When --sniff shadow is enabled and a backup/shadow copy is confirmed, OpenDoor stores the result in the shadow bucket. Shadow probes are active but bounded: they are generated only from confirmed 200 OK file-like hits and the shadow queue is drained before final summary, report generation and --fail-on-bucket checks. OpenDoor limits this active probing to 16 candidates per confirmed file-like hit and 500 total shadow probe requests per scan.
Detailed report items include:
| Field | Meaning |
|---|---|
shadow_detection.type |
Finding type, for example backup_copy |
shadow_detection.confidence |
Confidence score |
shadow_detection.reason |
Detection reason, for example content_match |
shadow_detection.base_url |
Original confirmed file used as the probe base |
shadow_detection.variant |
Matched suffix or template variant |
shadow_detection.variant_type |
Variant class: suffix or template |
shadow_detection.similarity |
Similarity score |
shadow_detection.base_size |
Base response size |
shadow_detection.shadow_size |
Shadow response size |
Report support:
| Report | Shadow evidence |
|---|---|
std |
Shows the shadow bucket and shadow counter in summary statistics |
txt |
Includes shadow evidence in shadow report lines |
json |
Preserves full metadata in report_items |
csv |
Adds dedicated shadow columns |
html |
Preserves detailed report_items metadata |
sqlite |
Stores shadow metadata in nullable item columns |
sarif |
Preserves shadow evidence in SARIF result properties |
Redirect classification metadata
Discovered 3xx responses are passively classified from their existing Location header. This is report enrichment for the normal redirect bucket; OpenDoor does not create a separate redirect-classifier report, does not follow redirects by default and does not add requests by default. Explicit --follow-redirects can materialize bounded same-host redirect chains and report only meaningful final non-redirect responses while keeping failed or homepage-collapse chains as passive redirect evidence.
| Marker | Meaning |
|---|---|
canonical |
Same-origin canonical redirect, such as /api to /api/ |
internal |
Same-origin redirect without a stronger class |
login |
Auth/login bounce |
logout |
Logout/session bounce |
external |
Cross-origin redirect target |
scheme |
Scheme change, such as HTTP to HTTPS |
asset |
Static asset/download redirect |
waf |
WAF or challenge redirect |
unknown |
Valid redirect without a confident class |
invalid |
Redirect status without a usable Location target |
Structured reports preserve bounded redirect_classification metadata with fields such as type, reason, location, target_url, target_scheme, target_host, target_path, same_origin, cross_origin and confidence. Sensitive query values in Location-like fields are redacted and long values are truncated.
R(external) is not an open redirect vulnerability claim. Confirmed open redirect vulnerabilities are reported only by --sniff openredirect.
Open redirect evidence
When --sniff openredirect is enabled and a redirect-like parameter is confirmed vulnerable, OpenDoor stores the result in the openredirect bucket. Open redirect verification is active but bounded: it uses discovered URLs that already contain redirect-like query parameters and verifies only controlled marker payloads such as https://opendoor.invalid/ or //opendoor.invalid/. OpenDoor does not follow the external redirect.
Detailed report items include:
| Field | Meaning |
|---|---|
openredirect_detection.type |
Finding type, currently open_redirect |
openredirect_detection.confidence |
Confidence score |
openredirect_detection.source_url |
Original discovered URL |
openredirect_detection.probe_url |
Controlled verification URL sent to the target |
openredirect_detection.parameter |
Redirect-like query parameter that accepted the marker payload |
openredirect_detection.payload |
Controlled marker payload |
openredirect_detection.variant |
Payload variant name |
openredirect_detection.location |
Confirmed Location header value |
openredirect_detection.marker_host |
Controlled marker host, by default opendoor.invalid |
Report support:
| Report | Open redirect evidence |
|---|---|
std |
Shows the openredirect bucket and counter in summary statistics |
txt |
Includes open redirect evidence in openredirect report lines |
json |
Preserves full metadata in report_items |
csv |
Adds dedicated openredirect columns |
html |
Preserves detailed report_items metadata |
sqlite |
Stores openredirect metadata in nullable item columns |
sarif |
Preserves openredirect evidence in SARIF result properties |
Header-bypass evidence
When --header-bypass is enabled and a candidate is found, OpenDoor stores the result in the bypass bucket.
Detailed report items include:
| Field | Meaning |
|---|---|
bypass |
Bypass type, currently header |
bypass_header |
Header that produced the candidate |
bypass_value |
Header value used for the probe |
bypass_from_code |
Original blocked status code |
bypass_to_code |
Resulting status code |
Report support:
| Report | Header-bypass evidence |
|---|---|
std |
Shows the bypass bucket in summary statistics |
txt |
Includes bypass evidence in bypass report lines |
json |
Preserves full metadata in report_items |
csv |
Adds dedicated bypass columns |
html |
Preserves detailed report_items metadata |
sqlite |
Stores bypass metadata in nullable item columns |
sarif |
Preserves bypass evidence in SARIF result properties |
CI/CD reports
opendoor \
--host https://example.com \
--reports json,sqlite,csv,sarif \
--fail-on-bucket success,auth,forbidden,bypass,shadow,openredirect
In CI/CD, prefer machine-readable formats such as json, sqlite, csv, and sarif.
Use the bypass bucket when Header Injection Bypass candidates should fail the pipeline. Use the shadow bucket when exposed backup/shadow copies should fail the pipeline. Use the endpoint bucket when client-exposed endpoint references should fail the pipeline. Use the openredirect bucket when confirmed open redirect vulnerabilities should fail the pipeline.
Report hygiene
Reports may contain sensitive findings.
Do not commit scan reports that include:
- private target URLs;
- internal paths;
- authentication-related endpoints;
- customer systems;
- cookies;
- tokens;
- private infrastructure details.
Store reports as CI artifacts or local evidence, not as public repository files.