@slicedearth/whoisleuth-cli 1.45.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DISCLOSURE +7 -3
- package/NOTICE +5 -4
- package/README.md +74 -124
- package/SECURITY.md +6 -3
- package/bin/whoisleuth.mjs +7 -4
- package/cli/archive-inspect.mjs +28 -10
- package/cli/arguments.mjs +450 -173
- package/cli/artifact-structure.mjs +2507 -0
- package/cli/artifact-verify.mjs +286 -64
- package/cli/bounded-json.mjs +1 -0
- package/cli/bulk-checkpoint.mjs +35 -23
- package/cli/bulk-command-runner.mjs +2 -5
- package/cli/bulk.mjs +9 -2
- package/cli/case-pack.mjs +435 -46
- package/cli/ci-report.mjs +6 -1
- package/cli/collection-preflight.mjs +2 -2
- package/cli/command-catalogue.mjs +12 -3
- package/cli/command-reference.mjs +948 -106
- package/cli/completion.mjs +504 -218
- package/cli/config-profile.mjs +13 -3
- package/cli/ct-event-intake.mjs +32 -2
- package/cli/discover.mjs +7 -1
- package/cli/discovery-observation-snapshot.mjs +24 -28
- package/cli/discovery-scan-command-runner.mjs +13 -14
- package/cli/discovery-scan.mjs +17 -3
- package/cli/discovery-snapshot.mjs +15 -7
- package/cli/discovery-workflow.mjs +2 -3
- package/cli/doctor.mjs +2 -2
- package/cli/domain-control-monitor.mjs +215 -36
- package/cli/domain-control-observations.mjs +34 -17
- package/cli/errors.mjs +8 -3
- package/cli/evidence-command-runner.mjs +17 -11
- package/cli/evidence-signing.mjs +68 -50
- package/cli/export-evidence.mjs +11 -4
- package/cli/external-observation-mapping.mjs +3 -3
- package/cli/formatters/html.mjs +3 -3
- package/cli/formatters/json.mjs +20 -32
- package/cli/formatters/terminal.mjs +586 -22
- package/cli/input.mjs +62 -0
- package/cli/interactive-launcher.mjs +226 -0
- package/cli/interchange-report.mjs +226 -0
- package/cli/investigation-manifest.mjs +16 -17
- package/cli/investigation-plan.mjs +167 -16
- package/cli/investigation-run.mjs +80 -24
- package/cli/local-mmdb-review.mjs +45 -14
- package/cli/lookalike-calibration.mjs +3 -1
- package/cli/lookup-brief.mjs +13 -8
- package/cli/lookup-browser.mjs +844 -0
- package/cli/lookup-command-runner.mjs +96 -33
- package/cli/lookup-diff.mjs +11 -2
- package/cli/lookup-plan.mjs +1 -0
- package/cli/mail-review.mjs +206 -94
- package/cli/manual.mjs +5 -5
- package/cli/network-command-runner.mjs +78 -0
- package/cli/offline-evidence-review.mjs +45 -14
- package/cli/open-asset-model-bridge.mjs +1 -1
- package/cli/output-file.mjs +70 -14
- package/cli/page-compare.mjs +18 -10
- package/cli/progress-events.mjs +2 -1
- package/cli/progress.mjs +3 -3
- package/cli/registry-cohort.mjs +343 -61
- package/cli/registry-doctor.mjs +67 -28
- package/cli/registry-support.mjs +2 -1
- package/cli/retained-artifact-diff.mjs +375 -0
- package/cli/risk-calibration.mjs +89 -40
- package/cli/runner.mjs +322 -246
- package/cli/saved-lookup.mjs +439 -49
- package/cli/sharing-review.mjs +18 -7
- package/cli/source-reliability.mjs +75 -36
- package/cli/terminal-presentation.mjs +43 -18
- package/docs/cli-reference.md +125 -1334
- package/docs/cli.md +87 -236
- package/frontend/src/lib/analysis/domain-control-manifest-core.js +3 -0
- package/frontend/src/lib/analysis/domain-control-records.js +3 -0
- package/lib/application-version.mjs +3 -0
- package/lib/availability.mjs +72 -52
- package/lib/bounded-contract-normalizers.mjs +2 -4
- package/lib/bounded-file.mjs +91 -4
- package/lib/bounded-json.mjs +287 -0
- package/lib/browser-library-profile.mjs +1 -1
- package/lib/certificate-extension-profile.mjs +2 -1
- package/lib/classify.mjs +56 -5
- package/lib/client-behavior-profile.mjs +1 -1
- package/lib/credential-surface-profile.mjs +1 -1
- package/lib/cryptographic-assurance.mjs +173 -0
- package/lib/ct-query.mjs +3 -3
- package/lib/ct-search.mjs +120 -64
- package/lib/distributed-operation-budget.mjs +4 -2
- package/lib/dns-delegation-health.mjs +9 -6
- package/lib/dns-intelligence.mjs +4 -3
- package/lib/dns-resolver-selection.mjs +6 -4
- package/lib/dnssec-chain-validation.mjs +1052 -0
- package/lib/dnssec-evidence-validation.mjs +23 -10
- package/lib/domain-assurance.mjs +12 -12
- package/lib/domain-change-packet.mjs +7 -5
- package/lib/domain-control-flight-recorder.mjs +442 -78
- package/lib/domain-control-manifest.mjs +314 -171
- package/lib/domain-posture-analysis.mjs +5 -2
- package/lib/domain-posture.mjs +7 -4
- package/lib/encrypted-dns-contract.mjs +2 -3
- package/lib/evidence-export.mjs +1243 -88
- package/lib/evidence-report-markdown.mjs +3 -0
- package/lib/evidence-report.mjs +5 -0
- package/lib/external-intelligence-risk.mjs +26 -10
- package/lib/favicon.mjs +8 -5
- package/lib/feature-policy.mjs +1 -1
- package/lib/homepage-metadata-contract.mjs +290 -0
- package/lib/hostname.mjs +1 -1
- package/lib/html-signals.mjs +89 -5
- package/lib/http-evidence-bounds.mjs +3 -0
- package/lib/http-intelligence.mjs +332 -6
- package/lib/interchange-fidelity-registry.mjs +124 -0
- package/lib/local-geoip-evidence.mjs +2 -1
- package/lib/lookup-cache.mjs +6 -4
- package/lib/lookup-network-evidence-bounds.mjs +9 -0
- package/lib/lookup.mjs +27 -4
- package/lib/observed-network-context.mjs +1 -1
- package/lib/outbound-identity.mjs +2 -3
- package/lib/page-fingerprints.mjs +2 -2
- package/lib/page-role-profile.mjs +1 -1
- package/lib/perceptual-hash.mjs +12 -4
- package/lib/portable-generator.mjs +29 -0
- package/lib/provider-policy-admission.mjs +11 -4
- package/lib/rdap-bootstrap.mjs +76 -16
- package/lib/rdap-client.mjs +20 -12
- package/lib/rdap-normalization.mjs +324 -80
- package/lib/rdap-registrar.mjs +5 -1
- package/lib/rdap-transport.mjs +2 -2
- package/lib/rdap-validation.mjs +65 -14
- package/lib/rdap.mjs +2 -2
- package/lib/registrable-domain.mjs +36 -0
- package/lib/registry-capabilities.mjs +3 -0
- package/lib/registry-capability-catalogue.mjs +12 -2
- package/lib/registry-comparison.mjs +28 -11
- package/lib/registry-insights.mjs +7 -0
- package/lib/response-policy.mjs +27 -4
- package/lib/risk-calibration-summary.mjs +340 -0
- package/lib/risk-scoring.mjs +4 -3
- package/lib/rpki-evidence.mjs +9 -8
- package/lib/safe-fetch.mjs +121 -50
- package/lib/security-txt.mjs +27 -4
- package/lib/service-binding-dns.mjs +6 -1
- package/lib/smtp-transport-review.mjs +787 -0
- package/lib/sslbl-certificates.generated.mjs +136 -134
- package/lib/sslbl-intelligence.mjs +6 -8
- package/lib/static-html-analysis.mjs +301 -4
- package/lib/structured-data-identity.mjs +51 -19
- package/lib/threat-intelligence-fixtures.mjs +2 -4
- package/lib/threat-intelligence-manifests.mjs +2 -7
- package/lib/threat-intelligence-runtime.mjs +5 -15
- package/lib/threat-intelligence-types.mjs +21 -1
- package/lib/threatfox-intelligence.mjs +7 -3
- package/lib/tls-intelligence.mjs +15 -9
- package/lib/tlsa-evidence.mjs +37 -7
- package/lib/urlhaus-intelligence.mjs +4 -2
- package/lib/urlscan-intelligence.mjs +6 -5
- package/lib/website-security-posture.mjs +1 -1
- package/lib/website-technology.mjs +1 -1
- package/lib/whois-authority.mjs +43 -8
- package/lib/whois-chain.mjs +25 -3
- package/lib/whois-normalization.mjs +3 -1
- package/lib/whois-transport.mjs +12 -3
- package/lib/zone-intent-review.mjs +1 -1
- package/package.json +12 -4
- package/packages/cases/case-brand-profile-references.mjs +85 -0
- package/{frontend/src/lib/analysis/case-evidence-model.js → packages/cases/case-evidence-model.mjs} +43 -14
- package/packages/cases/case-investigation-branch-model.mjs +132 -0
- package/packages/cases/case-migration-model.mjs +476 -0
- package/{frontend/src/lib/analysis/case-model.js → packages/cases/case-model.mjs} +3 -3
- package/{frontend/src/lib/analysis/case-record-contracts.js → packages/cases/case-record-contracts.mjs} +3 -19
- package/{frontend/src/lib/analysis/case-record-core.js → packages/cases/case-record-core.mjs} +58 -31
- package/packages/cases/case-record-model.mjs +9 -0
- package/{frontend/src/lib/analysis/case-record-operations.js → packages/cases/case-record-operations.mjs} +106 -33
- package/{frontend/src/lib/analysis/case-report.js → packages/cases/case-report.mjs} +143 -16
- package/packages/cases/case-response-model.mjs +1604 -0
- package/packages/cases/case-response-packet.mjs +1312 -0
- package/{frontend/src/lib/analysis/case-storage-model.js → packages/cases/case-storage-model.mjs} +2 -2
- package/{frontend/src/lib/analysis/http-summary.js → packages/cases/http-summary.mjs} +1 -1
- package/packages/cases/opaque-reference-id.mjs +9 -0
- package/packages/comparison/comparison-ledger-bulk.mjs +366 -0
- package/packages/comparison/comparison-ledger-contract.mjs +241 -0
- package/packages/comparison/comparison-ledger-json.mjs +80 -0
- package/packages/comparison/comparison-ledger-serialization.mjs +52 -0
- package/packages/comparison/favicon-similarity.mjs +78 -0
- package/{frontend/src/lib/analysis/page-similarity.js → packages/comparison/page-similarity.mjs} +4 -3
- package/{frontend/src/lib/analysis/relationship-evidence.js → packages/comparison/relationship-evidence.mjs} +6 -7
- package/packages/contracts/analyst-review-state-contract.mjs +61 -0
- package/packages/contracts/analyst-review-state.mjs +50 -0
- package/packages/contracts/case-portability.mjs +1310 -0
- package/packages/contracts/cli-command-catalogue.mjs +2 -0
- package/packages/contracts/cli-lookup.mjs +394 -0
- package/packages/contracts/domain-control-flight-recorder.mjs +461 -0
- package/packages/contracts/domain-control-manifest.mjs +1027 -0
- package/packages/contracts/domain-control-monitor.mjs +310 -0
- package/packages/contracts/domain-control-review.mjs +828 -0
- package/packages/contracts/domain-name.mjs +4 -0
- package/packages/contracts/external-observation-interchange.mjs +224 -0
- package/packages/contracts/extracted-domain-lifecycle.mjs +218 -0
- package/packages/contracts/investigation-portability.mjs +331 -0
- package/packages/contracts/offline-comparison.mjs +160 -0
- package/packages/contracts/risk-calibration.mjs +1288 -0
- package/packages/contracts/schema-compatibility.mjs +71 -0
- package/packages/contracts/schema-lifecycle.mjs +1702 -0
- package/packages/contracts/sslbl-snapshot.mjs +17 -0
- package/packages/contracts/workspace-portability.mjs +1347 -0
- package/packages/evidence/artifact-integrity.mjs +65 -0
- package/packages/evidence/decision-fact.mjs +735 -0
- package/packages/evidence/domain-control-runtime.mjs +547 -0
- package/packages/evidence/domain-name.mjs +41 -0
- package/packages/evidence/observation.mjs +384 -0
- package/{frontend/src/lib/analysis/external-findings-import.js → packages/interchange/external-findings-import.mjs} +86 -20
- package/packages/interchange/retained-text.mjs +8 -0
- package/{frontend/src/lib/analysis/acquisition-decision-packet.js → packages/investigation/acquisition-decision-packet.mjs} +11 -8
- package/{frontend/src/lib/analysis/bulk-domain-comparison.js → packages/investigation/bulk-domain-comparison.mjs} +28 -9
- package/{frontend/src/lib/analysis/bulk-mail-exposure.js → packages/investigation/bulk-mail-exposure.mjs} +67 -18
- package/{frontend/src/lib/analysis/bulk-review-export.js → packages/investigation/bulk-review-export.mjs} +10 -9
- package/packages/investigation/bulk-review-policy.mjs +1 -0
- package/{frontend/src/lib/analysis/investigation-capsule.js → packages/investigation/investigation-capsule.mjs} +50 -18
- package/packages/investigation/lookup-artefact-inputs.mjs +1 -0
- package/{frontend/src/lib/analysis/lookup-asset-graph.js → packages/investigation/lookup-asset-graph.mjs} +4 -2
- package/packages/investigation/lookup-claim-passport.mjs +232 -0
- package/packages/investigation/lookup-claim-readiness.mjs +287 -0
- package/packages/investigation/lookup-investigation-brief.mjs +172 -0
- package/packages/monitoring/analyst-review-state.mjs +680 -0
- package/{frontend/src/lib/analysis/brand-profile-model.js → packages/workspace/brand-profile-model.mjs} +97 -50
- package/{frontend/src/lib/analysis/bulk-review-model.js → packages/workspace/bulk-review-model.mjs} +15 -15
- package/{frontend/src/lib/analysis/bulk-session-model.js → packages/workspace/bulk-session-model.mjs} +179 -39
- package/{frontend/src/lib/analysis/bulk-sort.js → packages/workspace/bulk-sort.mjs} +12 -5
- package/{frontend/src/lib/analysis/campaign-model.js → packages/workspace/campaign-model.mjs} +20 -22
- package/{frontend/src/lib/analysis/detection-rule-model.js → packages/workspace/detection-rule-model.mjs} +15 -17
- package/packages/workspace/hostile-input.mjs +172 -0
- package/{frontend/src/lib/analysis/investigation-guide.js → packages/workspace/investigation-guide.mjs} +51 -46
- package/{frontend/src/lib/analysis/investigation-template-model.js → packages/workspace/investigation-template-model.mjs} +15 -15
- package/{frontend/src/lib/analysis/page-baseline.js → packages/workspace/page-baseline.mjs} +6 -13
- package/{frontend/src/lib/analysis/relationship-observation-model.js → packages/workspace/relationship-observation-model.mjs} +13 -17
- package/{frontend/src/lib/analysis/shortlist-model.js → packages/workspace/shortlist-model.mjs} +20 -18
- package/{frontend/src/lib/analysis/watchlist-history.js → packages/workspace/watchlist-history.mjs} +9 -16
- package/{frontend/src/lib/analysis/watchlist-store.js → packages/workspace/watchlist-store.mjs} +24 -17
- package/{frontend/src/lib/analysis/website-snapshot-model.js → packages/workspace/website-snapshot-model.mjs} +18 -12
- package/{frontend/src/lib/analysis/workspace-archive-crypto.js → packages/workspace/workspace-archive-crypto.mjs} +49 -19
- package/{frontend/src/lib/analysis/workspace-archive.js → packages/workspace/workspace-archive.mjs} +195 -84
- package/third-party-notices.txt +112 -5834
- package/frontend/src/lib/analysis/artifact-integrity.js +0 -21
- package/frontend/src/lib/analysis/bulk-retry-plan.js +0 -79
- package/frontend/src/lib/analysis/bulk-source-coverage.js +0 -76
- package/frontend/src/lib/analysis/case-migration-model.js +0 -253
- package/frontend/src/lib/analysis/case-record-model.js +0 -7
- package/frontend/src/lib/analysis/case-response-model.js +0 -669
- package/frontend/src/lib/analysis/case-response-packet.js +0 -573
- package/frontend/src/lib/analysis/lookup-decision-support.js +0 -487
- package/frontend/src/lib/analysis/lookup-investigation-brief.js +0 -153
- package/frontend/src/lib/analysis/lookup-presentation.js +0 -58
- package/frontend/src/lib/analysis/lookup-response.js +0 -2
- package/frontend/src/lib/analysis/lookup-source-refresh.js +0 -277
- package/frontend/src/lib/analysis/lookup-summary-model.js +0 -398
- package/frontend/src/lib/analysis/scoring.js +0 -55
- package/frontend/src/lib/analysis/utils.js +0 -232
- package/frontend/src/lib/analysis/visualization-bounds.js +0 -26
- package/frontend/src/lib/analysis/visualization-force-graph.js +0 -352
- package/frontend/src/lib/analysis/visualization-matrix.js +0 -88
- package/frontend/src/lib/analysis/visualization-models.js +0 -369
- package/frontend/src/lib/analysis/visualization-time-series.js +0 -144
- package/lib/bounded-json-response.mjs +0 -157
- package/lib/lookup-response-contract.mjs +0 -346
- package/lib/observation.mjs +0 -114
- /package/{frontend/src/lib/analysis/acquisition-due-diligence.js → packages/investigation/acquisition-due-diligence.mjs} +0 -0
- /package/{frontend/src/lib/analysis/evidence-coverage-ledger.js → packages/investigation/evidence-coverage-ledger.mjs} +0 -0
- /package/{frontend/src/lib/analysis/dns-record-normalization.js → packages/workspace/dns-record-normalization.mjs} +0 -0
package/docs/cli-reference.md
CHANGED
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
# WHOISleuth CLI reference
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
The WHOISleuth CLI runs locally. Installed `whoisleuth <command> --help`,
|
|
4
|
+
`whoisleuth commands` and `whoisleuth manual` are the exact grammar, option and
|
|
5
|
+
command authorities for that installed version. The public
|
|
6
|
+
[CLI reference](https://whoisleuth.com/cli) provides a searchable view generated
|
|
7
|
+
from the same registry.
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`whoisleuth --help` displays the copyright, AGPL-3.0-only licence, and official
|
|
11
|
-
source location. It groups commands by investigation, discovery, saved-evidence,
|
|
12
|
-
integrity, and calibration workflows. `whoisleuth <command> --help` displays the
|
|
13
|
-
command's purpose, focused invocation, example, and collection boundary without
|
|
14
|
-
printing the full command list. `whoisleuth commands --json` exposes those same
|
|
15
|
-
contracts as a stable local catalogue for wrappers and terminal tooling.
|
|
16
|
-
Packaged copies include `LICENSE`, `NOTICE`, and
|
|
17
|
-
`TRADEMARKS.md` alongside the CLI documentation.
|
|
9
|
+
This page records the common interfaces and the boundaries that matter across
|
|
10
|
+
commands. The generated [privacy/data-flow catalogue](https://github.com/slicedearth/whoisleuth/blob/main/docs/privacy-data-flow-catalogue.md)
|
|
11
|
+
contains the exhaustive recipient, retention and export metadata.
|
|
18
12
|
|
|
19
13
|
## Installation
|
|
20
14
|
|
|
21
|
-
Public releases require Node.js 24 or later
|
|
22
|
-
command:
|
|
15
|
+
Public releases require Node.js 24 or later:
|
|
23
16
|
|
|
24
17
|
```bash
|
|
25
18
|
npm exec --yes --ignore-scripts --package=@slicedearth/whoisleuth-cli -- whoisleuth --help
|
|
@@ -27,1329 +20,127 @@ npm install --global --ignore-scripts @slicedearth/whoisleuth-cli
|
|
|
27
20
|
whoisleuth doctor
|
|
28
21
|
```
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
whoisleuth --version
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
The scoped package and application share one semantic version. The package runs
|
|
38
|
-
locally and does not call the hosted WHOISleuth deployment. Networked commands
|
|
39
|
-
contact only the sources described by their collection profile; offline review,
|
|
40
|
-
comparison, verification, completion, and manual commands remain local.
|
|
41
|
-
|
|
42
|
-
## Commands
|
|
23
|
+
The scoped package and application share one semantic version. The package
|
|
24
|
+
requires no dependency lifecycle scripts and does not call the hosted
|
|
25
|
+
WHOISleuth deployment. From a repository checkout, replace `whoisleuth` with
|
|
26
|
+
`node bin/whoisleuth.mts`.
|
|
43
27
|
|
|
44
|
-
|
|
45
|
-
node bin/whoisleuth.mts lookup example.com
|
|
46
|
-
node bin/whoisleuth.mts lookup AS13335 --json
|
|
47
|
-
printf 'example.com\n' | node bin/whoisleuth.mts lookup --json
|
|
48
|
-
node bin/whoisleuth.mts lookup example.com --deep
|
|
49
|
-
node bin/whoisleuth.mts lookup example.com --deep --plan --json
|
|
50
|
-
node bin/whoisleuth.mts lookup example.com --deep --summary
|
|
51
|
-
node bin/whoisleuth.mts lookup example.com --deep --verbose
|
|
52
|
-
node bin/whoisleuth.mts lookup example.com --deep --markdown --output lookup.md
|
|
53
|
-
node bin/whoisleuth.mts lookup example.com --deep --json --strict-exit --events
|
|
54
|
-
node bin/whoisleuth.mts lookup example.test --deep --observer workstation-a --vantage office-egress --json > office.json
|
|
55
|
-
cat domains.txt | node bin/whoisleuth.mts bulk --jsonl
|
|
56
|
-
node bin/whoisleuth.mts bulk domains.txt --csv --registered-only
|
|
57
|
-
node bin/whoisleuth.mts bulk domains.txt --domains --inconclusive-only
|
|
58
|
-
node bin/whoisleuth.mts bulk domains.txt --queries --errors-only
|
|
59
|
-
node bin/whoisleuth.mts bulk domains.txt --concurrency 4
|
|
60
|
-
node bin/whoisleuth.mts bulk domains.txt --deep --checkpoint bulk-checkpoint.json
|
|
61
|
-
node bin/whoisleuth.mts bulk domains.txt --deep --checkpoint bulk-checkpoint.json --resume
|
|
62
|
-
node bin/whoisleuth.mts ct-search 'example brand' --json
|
|
63
|
-
node bin/whoisleuth.mts discover example.com --preset common --jsonl
|
|
64
|
-
node bin/whoisleuth.mts discover example.test --dictionary private-terms.txt --snapshot discovery-state.json --json
|
|
65
|
-
node bin/whoisleuth.mts discover-scan example.test --scan-limit 50 --checkpoint candidate-scan.json --json
|
|
66
|
-
node bin/whoisleuth.mts discover-scan example.test --deep --scan-limit 20 --resolver 192.0.2.53 --observation-snapshot observed-candidates.json --csv
|
|
67
|
-
node bin/whoisleuth.mts posture example.com --selectors selector1 --retired-selectors selector0 --mail-profile defensive-no-mail --json
|
|
68
|
-
node bin/whoisleuth.mts http example.com --json
|
|
69
|
-
node bin/whoisleuth.mts tls example.com --json
|
|
70
|
-
node bin/whoisleuth.mts registry-support example.uk --json
|
|
71
|
-
node bin/whoisleuth.mts registry-doctor lookup.json --json
|
|
72
|
-
node bin/whoisleuth.mts registry-cohort saved-lookups.jsonl --json
|
|
73
|
-
node bin/whoisleuth.mts registry-scaffold --profile example-profile --suffix test --scenario registered
|
|
74
|
-
node bin/whoisleuth.mts risk-calibrate calibration.json --json
|
|
75
|
-
node bin/whoisleuth.mts lookalike-calibrate reviewed-candidates.json --json
|
|
76
|
-
node bin/whoisleuth.mts verify-artifact workspace.json --json
|
|
77
|
-
node bin/whoisleuth.mts verify-artifact lookup.json --json
|
|
78
|
-
node bin/whoisleuth.mts verify-artifact workspace-encrypted.json --passphrase-file passphrase.txt --json
|
|
79
|
-
node bin/whoisleuth.mts source-report lookup.json --json
|
|
80
|
-
node bin/whoisleuth.mts inspect-archive workspace.json --json
|
|
81
|
-
node bin/whoisleuth.mts inspect-archive workspace.json --search example.invalid --json
|
|
82
|
-
node bin/whoisleuth.mts sign-artifact response-packet.json --private-key-file analyst-private.pem > response-packet.signed.json
|
|
83
|
-
node bin/whoisleuth.mts ct-intake certificate-events.json --json > external-findings.json
|
|
84
|
-
node bin/whoisleuth.mts map-observations observation-mapping.json --json > external-findings.json
|
|
85
|
-
node bin/whoisleuth.mts oam-export external-findings.json --json > asset-bridge.json
|
|
86
|
-
node bin/whoisleuth.mts manifest lookup.json comparison.json --workflow 'domain review' --json > investigation-manifest.json
|
|
87
|
-
node bin/whoisleuth.mts verify-signature response-packet.signed.json --public-key-file analyst-public.pem
|
|
88
|
-
node bin/whoisleuth.mts lookup example.com --deep --json > lookup.json
|
|
89
|
-
node bin/whoisleuth.mts compare lookup.json --json
|
|
90
|
-
node bin/whoisleuth.mts page-compare official.json candidate.json --json
|
|
91
|
-
node bin/whoisleuth.mts mail-review bulk.json --json
|
|
92
|
-
node bin/whoisleuth.mts review-evidence dnssec-evidence.json --json
|
|
93
|
-
node bin/whoisleuth.mts review-evidence trust-store-comparison.json --json
|
|
94
|
-
node bin/whoisleuth.mts domain-control domain-control-input.json --json
|
|
95
|
-
node bin/whoisleuth.mts assurance domain-assurance-input.json --json
|
|
96
|
-
node bin/whoisleuth.mts change-packet domain-change-packet-input.json --json
|
|
97
|
-
node bin/whoisleuth.mts sharing-review response-packet.json --marking amber --recipient-scope organization --purpose 'Reviewed incident handoff' --human-reviewed --personal-data-reviewed --redactions-confirmed --json
|
|
98
|
-
node bin/whoisleuth.mts workflow-plan domain-triage example.test --json
|
|
99
|
-
node bin/whoisleuth.mts workflow-run domain-triage example.test --approve-network --json --output run.json
|
|
100
|
-
node bin/whoisleuth.mts brief lookup.json
|
|
101
|
-
node bin/whoisleuth.mts case-pack cases.json --audience trusted --reviewed --json
|
|
102
|
-
node bin/whoisleuth.mts monitor-once control-manifest.json --previous prior-control.json --junit
|
|
103
|
-
node bin/whoisleuth.mts diff first-lookup.json second-lookup.json --json
|
|
104
|
-
node bin/whoisleuth.mts reconcile office.json mobile.json external.json --json
|
|
105
|
-
node bin/whoisleuth.mts timeline first-observation.json second-observation.json latest-observation.json --json
|
|
106
|
-
node bin/whoisleuth.mts export lookup.json > evidence.json
|
|
107
|
-
node bin/whoisleuth.mts export lookup.json --markdown > evidence.md
|
|
108
|
-
node bin/whoisleuth.mts export lookup.json --html > evidence.html
|
|
109
|
-
node bin/whoisleuth.mts doctor
|
|
110
|
-
node bin/whoisleuth.mts doctor --network --json
|
|
111
|
-
node bin/whoisleuth.mts commands --json
|
|
112
|
-
node bin/whoisleuth.mts completion zsh
|
|
113
|
-
node bin/whoisleuth.mts completion powershell
|
|
114
|
-
node bin/whoisleuth.mts manual | man -l -
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
These examples run from a checked-out repository; replace
|
|
118
|
-
`node bin/whoisleuth.mts` with `whoisleuth` after installation. The root
|
|
119
|
-
application package remains private. A separate scoped CLI archive is assembled
|
|
120
|
-
from the exact executable dependency closure, installed in a temporary
|
|
121
|
-
directory, and smoke tested with:
|
|
28
|
+
## Find and inspect commands
|
|
122
29
|
|
|
123
30
|
```bash
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
deployment adapters, tests, and development tools. Direct runtime dependencies
|
|
130
|
-
are pinned to the exact versions exercised by the reviewed repository lockfile.
|
|
131
|
-
The package and its dependencies require no lifecycle scripts, so the install
|
|
132
|
-
examples disable them explicitly.
|
|
133
|
-
Its generated manifest stays private. Release-candidate assembly is a separate
|
|
134
|
-
explicit operation and never publishes from a developer checkout. Use the
|
|
135
|
-
scoped package name; an unqualified `npx whoisleuth` is not this project.
|
|
136
|
-
|
|
137
|
-
Lookup defaults to the conservative fast profile. `--deep` must be requested
|
|
138
|
-
explicitly and can add bounded WHOIS, DNS, website, TLS, registrar RDAP, and
|
|
139
|
-
observed-network IP RDAP work for a domain. The browser Console's optional
|
|
140
|
-
security.txt and external intelligence selections are not CLI flags; the CLI
|
|
141
|
-
does not run those actions implicitly.
|
|
142
|
-
|
|
143
|
-
For a directly entered public IP address, `lookup --deep` can also run one
|
|
144
|
-
bounded reverse-DNS query. Terminal output shows the explicit source state and
|
|
145
|
-
up to five normalised PTR names; JSON retains up to eight. PTR names are
|
|
146
|
-
operator-published routing context, not proof of hosting control or ownership.
|
|
147
|
-
Fast lookups do not run this query.
|
|
148
|
-
|
|
149
|
-
`lookup --plan` performs classification and prints a versioned preflight without
|
|
150
|
-
starting collection. It lists the normalised target, selected fast or deep
|
|
151
|
-
mode, planned source families, conditional operations, and the data each family
|
|
152
|
-
may receive. The plan cannot predict live feature configuration, cache state,
|
|
153
|
-
redirects, referrals, source availability, or an exact request count. It can be
|
|
154
|
-
combined with `--json`, but not with report, detail, strict-exit, progress-event,
|
|
155
|
-
or quiet options.
|
|
156
|
-
|
|
157
|
-
Only one query is accepted by `lookup`. Multiple-input processing belongs to
|
|
158
|
-
the explicit `bulk` command rather than being silently inferred by `lookup`.
|
|
159
|
-
Standard input is capped at 4 KiB and must contain one non-empty line.
|
|
160
|
-
|
|
161
|
-
`registry-support` is an offline catalogue view. It accepts one domain, bare
|
|
162
|
-
suffix, or leading-dot suffix as an argument or on stdin and makes no network
|
|
163
|
-
request. Its output is described below.
|
|
164
|
-
|
|
165
|
-
`doctor` is offline by default. It checks the Node runtime, platform, terminal
|
|
166
|
-
capabilities, and availability of offline command families. `doctor --network`
|
|
167
|
-
adds independent bounded public-DNS, HTTPS/RDAP bootstrap, and WHOIS port 43
|
|
168
|
-
checks against fixed IANA diagnostic infrastructure. The three probes run
|
|
169
|
-
within the same per-probe ceiling so one stalled transport does not block the
|
|
170
|
-
others. The report retains only state, HTTP status, and a bounded explanation,
|
|
171
|
-
not resolved addresses or response content. A failed optional network check
|
|
172
|
-
returns the partial-failure exit code rather than claiming that all CLI
|
|
173
|
-
collection is unavailable.
|
|
174
|
-
|
|
175
|
-
`completion bash`, `completion zsh`, `completion fish`, and `completion
|
|
176
|
-
powershell` print static shell completion scripts to stdout. The command does
|
|
177
|
-
not edit a shell profile or make a network request. Review the generated script
|
|
178
|
-
before sourcing it or placing it in the relevant shell completion directory.
|
|
179
|
-
`manual` prints a generated roff manual page and likewise changes no local
|
|
180
|
-
configuration.
|
|
181
|
-
|
|
182
|
-
`commands` prints the installed command catalogue without running collection or
|
|
183
|
-
reading evidence. `commands --json` emits version 1 of the
|
|
184
|
-
`whoisleuth.cli.command-catalogue` schema, including each command's usage,
|
|
185
|
-
example, declared collection mode, collection scope, and boundary. This is the
|
|
186
|
-
supported discovery contract for local wrappers; it is not a permission grant
|
|
187
|
-
or a substitute for focused help.
|
|
188
|
-
|
|
189
|
-
Focused command help and the generated manual classify every operation as
|
|
190
|
-
offline or networked and state the relevant target, input, and concurrency
|
|
191
|
-
ceiling. These labels describe observable behaviour rather than granting
|
|
192
|
-
authorisation. The packaged `DISCLOSURE` defines the intended defensive scope;
|
|
193
|
-
operators remain responsible for law, provider terms, and authorisation.
|
|
194
|
-
|
|
195
|
-
## Deployment boundary
|
|
196
|
-
|
|
197
|
-
The CLI runs locally. The serverless deployment publishes only `frontend/build`
|
|
198
|
-
and packages functions only from `netlify/functions`, so `bin/` and `cli/` are
|
|
199
|
-
not part of the hosted static site or function bundle. The application root and
|
|
200
|
-
ordinary package-check candidate remain private. Explicitly reviewed CLI
|
|
201
|
-
release candidates can be published under the scoped public package described
|
|
202
|
-
in the installation section.
|
|
203
|
-
|
|
204
|
-
Commands that query RDAP, WHOIS, DNS, HTTP, TLS, or Certificate Transparency do
|
|
205
|
-
so directly from the machine running the CLI. They do not use the hosted login,
|
|
206
|
-
hosted session, or deployment usage controls; upstream providers can see and
|
|
207
|
-
rate-limit the local machine's network address. Offline `discover`, `compare`,
|
|
208
|
-
`page-compare`, `mail-review`, `review-evidence`, `domain-control`, `assurance`, `change-packet`,
|
|
209
|
-
`sharing-review`, `workflow-plan`, `brief`, `case-pack`, `registry-cohort`,
|
|
210
|
-
`registry-scaffold`, `diff`, `reconcile`, `timeline`,
|
|
211
|
-
`risk-calibrate`, `lookalike-calibrate`, `registry-doctor`, `verify-artifact`, `source-report`,
|
|
212
|
-
`map-observations`, `oam-export`, `export`,
|
|
213
|
-
`commands`, `completion`, and `manual` operations make no network requests. Commands write
|
|
214
|
-
to stdout unless the analyst deliberately selects a local output file.
|
|
215
|
-
|
|
216
|
-
## Output
|
|
217
|
-
|
|
218
|
-
Human-readable terminal output is the default. On an interactive terminal it
|
|
219
|
-
uses restrained semantic colour, groups Lookup evidence by purpose, wraps
|
|
220
|
-
prose to the detected terminal width, and shows transient progress on stderr
|
|
221
|
-
for slower collection. State remains explicit in text, so colour is never the
|
|
222
|
-
only distinction. Redirected terminal output, JSON, and JSONL contain no ANSI
|
|
223
|
-
sequences or progress text. `--no-color` and a non-empty conventional
|
|
224
|
-
`NO_COLOR` environment variable disable colour; `WHOISLEUTH_NO_PROGRESS=1`
|
|
225
|
-
disables the transient indicator. Command examples remain one copyable line
|
|
226
|
-
even when prose is wrapped for a narrow terminal.
|
|
227
|
-
|
|
228
|
-
Every command accepts `--output <file>` as a safer alternative to shell
|
|
229
|
-
redirection. WHOISleuth buffers bounded output, creates a private temporary file
|
|
230
|
-
beside the destination, syncs it, and publishes it atomically with mode `0600`.
|
|
231
|
-
An existing destination is refused. `--force` is valid only with `--output` and
|
|
232
|
-
allows an intentional atomic replacement. A failed or cancelled command does
|
|
233
|
-
not publish a partial output file. Output is capped at 32 MiB.
|
|
234
|
-
|
|
235
|
-
`--config <file> --profile <name>` reads a strict version-1 local configuration
|
|
236
|
-
document of at most 64 KiB. Without `--config`, the path is
|
|
237
|
-
`$XDG_CONFIG_HOME/whoisleuth/config.json`. A profile may contain no more than
|
|
238
|
-
16 safe defaults drawn from `--no-color`, `--summary`, `--verbose`, `--fast`,
|
|
239
|
-
`--concurrency`, `--observer`, and `--vantage`. It cannot supply a target,
|
|
240
|
-
Deep mode, output path, network approval, failure policy, credential, or
|
|
241
|
-
arbitrary argument. Explicit command options override profile defaults from
|
|
242
|
-
the same group.
|
|
243
|
-
|
|
244
|
-
Lookup, Bulk, and `monitor-once` can emit bounded JUnit XML. Owned-domain
|
|
245
|
-
Posture can emit SARIF only when `--owned-domain` confirms the passive target
|
|
246
|
-
boundary. The reports contain categorical source or posture findings rather
|
|
247
|
-
than raw evidence. Supported network commands accept an explicit comma-
|
|
248
|
-
separated `--fail-on` policy from `source-failure`, `inconclusive`, `danger`,
|
|
249
|
-
and `material-drift`; a match returns the partial-result exit code after the
|
|
250
|
-
normal output is emitted.
|
|
251
|
-
|
|
252
|
-
`lookup --markdown` and `lookup --html` build the existing normalised evidence
|
|
253
|
-
report directly after one completed domain lookup. They do not start a second
|
|
254
|
-
collection. These report formats reject IP and ASN inputs before collection;
|
|
255
|
-
JSON and terminal output remain available for those query types.
|
|
256
|
-
|
|
257
|
-
Lookup terminal output supports three detail levels. The standard view keeps
|
|
258
|
-
the normal bounded evidence summary. `--summary` keeps the source states and
|
|
259
|
-
key findings while omitting endpoints and supporting detail. `--verbose` adds
|
|
260
|
-
the document generation time and the existing bounded per-source collection
|
|
261
|
-
timings. These switches are presentation-only and cannot be combined with
|
|
262
|
-
`--json`; they do not change collection or the result document.
|
|
263
|
-
|
|
264
|
-
`--json` writes one versioned document to standard output:
|
|
265
|
-
|
|
266
|
-
```json
|
|
267
|
-
{
|
|
268
|
-
"schema": "whoisleuth.cli.lookup",
|
|
269
|
-
"version": 1,
|
|
270
|
-
"generatedAt": "2026-07-14T00:00:00.000Z",
|
|
271
|
-
"mode": "fast",
|
|
272
|
-
"query": "example.com",
|
|
273
|
-
"type": "domain"
|
|
274
|
-
}
|
|
31
|
+
whoisleuth --help
|
|
32
|
+
whoisleuth commands --common
|
|
33
|
+
whoisleuth commands --group investigate --mode network
|
|
34
|
+
whoisleuth lookup --help
|
|
35
|
+
whoisleuth lookup example.test --deep --plan --json
|
|
275
36
|
```
|
|
276
37
|
|
|
277
|
-
The
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
partial final result, flushes an enabled Bulk checkpoint, and exits with code
|
|
333
|
-
130. SIGTERM follows the same graceful cleanup path and exits with code 143.
|
|
334
|
-
Already started network operations remain subject to their existing hard
|
|
335
|
-
timeouts while the shared in-process API unwinds; the executable terminates
|
|
336
|
-
after CLI cleanup. A second Ctrl-C removes any known unpublished temporary
|
|
337
|
-
output file on a best-effort basis before exiting immediately.
|
|
338
|
-
|
|
339
|
-
Bulk can persist compact progress with `--checkpoint <file>`. A new checkpoint
|
|
340
|
-
is private, bounded to 16 MiB, versioned, and tied to the exact ordered input
|
|
341
|
-
and scan mode by SHA-256. It stores only compact per-item results, never full
|
|
342
|
-
Lookup responses. Checkpoint schema 2 records a nullable per-row observation
|
|
343
|
-
time. Schema 1 remains readable, but its resumed rows keep observation time
|
|
344
|
-
unknown rather than inheriting the resume time. Reusing the same path is
|
|
345
|
-
refused unless `--resume` is also
|
|
346
|
-
specified. Resume revalidates the complete untrusted document and skips only
|
|
347
|
-
the exact completed rows; changed input, mode, schema, digest, or malformed
|
|
348
|
-
results fail closed.
|
|
349
|
-
|
|
350
|
-
Bulk JSON, JSONL, and item documents use schema version 3. Each row includes
|
|
351
|
-
`observedAt` and a `collectionOrigin` of `current_run` or
|
|
352
|
-
`resumed_checkpoint`; the top-level `generatedAt` remains the report creation
|
|
353
|
-
time. HTTP JSON uses schema version 2 and adds the explicit `assessment` field.
|
|
354
|
-
The legacy `activityStatus` field remains for compatibility, but is `null`
|
|
355
|
-
when collection is inconclusive rather than labelling the target unreachable.
|
|
356
|
-
Consumers should use `assessment`; older version-1 `unreachable` values remain
|
|
357
|
-
historical inconclusive labels, not proof that a target cannot be reached.
|
|
358
|
-
|
|
359
|
-
If checkpoint persistence fails after collection, WHOISleuth still emits the
|
|
360
|
-
completed final result, reports the checkpoint limitation, and exits with code
|
|
361
|
-
4. The last successfully published checkpoint remains available, but it may
|
|
362
|
-
not contain the final completed items.
|
|
363
|
-
|
|
364
|
-
`diff <left.json> <right.json>` compares two different saved domain Lookup
|
|
365
|
-
documents entirely offline. It reuses the bounded Bulk comparison model for
|
|
366
|
-
registration, DNS, page identity, mail, certificate, and relationship fields,
|
|
367
|
-
keeps missing and unavailable evidence distinct, and makes no ownership or
|
|
368
|
-
maliciousness inference. The output records both original observation times.
|
|
369
|
-
|
|
370
|
-
`lookup --observer <label> --vantage <label>` can add two bounded analyst labels
|
|
371
|
-
to a saved Lookup document. The labels identify the person or process that ran
|
|
372
|
-
the observation and the collection context chosen by that analyst; they are
|
|
373
|
-
not verified identities, network measurements, or proof of independent
|
|
374
|
-
collection. They do not change which sources are queried.
|
|
375
|
-
|
|
376
|
-
`reconcile <observation.json> <observation.json> [...]` accepts from 2 to 5
|
|
377
|
-
saved Lookup documents for the same domain and compares their bounded fields
|
|
378
|
-
offline. It keeps agreement, disagreement, and non-comparable evidence
|
|
379
|
-
separate, retains observation times and optional analyst labels, and copies no
|
|
380
|
-
filenames or raw registration payloads. Distinct complete label pairs are
|
|
381
|
-
reported as labelled collection contexts only; majority agreement is not
|
|
382
|
-
treated as truth or authority.
|
|
383
|
-
|
|
384
|
-
`timeline <observation.json> <observation.json> [...]` accepts from 2 to 20
|
|
385
|
-
saved Lookup documents for one domain, orders them by their validated
|
|
386
|
-
observation times, and compares each adjacent pair offline. The 32 MiB aggregate
|
|
387
|
-
input ceiling is enforced while files are read and again by the timeline
|
|
388
|
-
builder. Output retains normalised field states and observation times but no
|
|
389
|
-
input filenames or raw registry payloads. A difference can reflect a domain
|
|
390
|
-
change or changed collection conditions, so the command makes no current-state,
|
|
391
|
-
ownership, intent, safety, or maliciousness conclusion.
|
|
392
|
-
|
|
393
|
-
When diagnostics version 5, 6, 7, or 8 reports a documented registry collection
|
|
394
|
-
constraint, terminal output also shows the suffix, WHOIS and RDAP access
|
|
395
|
-
profiles, and the bounded limitation. This is static access-policy context: it
|
|
396
|
-
does not make another request, and restricted, unpublished, or unavailable
|
|
397
|
-
machine access is not evidence that a domain is unregistered or safe.
|
|
398
|
-
|
|
399
|
-
## Exit codes
|
|
38
|
+
The command index groups work under Investigate, Respond, Assure and Utilities.
|
|
39
|
+
Filters combine by intersection. `commands --json` emits the versioned local
|
|
40
|
+
catalogue without reading evidence or running the selected commands.
|
|
41
|
+
|
|
42
|
+
An eligible domain, reserved documentation domain, IP address or ASN can occupy
|
|
43
|
+
command position as Lookup shorthand. Use explicit `lookup` where input needs
|
|
44
|
+
supported URL-like normalisation. Credentials, paths, queries, fragments, ports
|
|
45
|
+
and unsupported special-use targets are rejected by the shorthand.
|
|
46
|
+
|
|
47
|
+
`registry-scaffold` has a separate fixture contract: its `--profile` selects one
|
|
48
|
+
fixed fixture profile and shared `--config` profiles are rejected. It produces
|
|
49
|
+
sanitised local fixture material and makes no registry request.
|
|
50
|
+
|
|
51
|
+
## Requests and authorisation
|
|
52
|
+
|
|
53
|
+
Offline commands read only supplied arguments, files, standard input and
|
|
54
|
+
installed catalogues. Networked commands contact the sources named by their
|
|
55
|
+
focused help; those sources can observe and rate-limit the operator's network
|
|
56
|
+
address. The CLI does not inherit hosted login, provider configuration or
|
|
57
|
+
hosted operation limits.
|
|
58
|
+
|
|
59
|
+
`lookup --plan` classifies a target and lists intended source families and
|
|
60
|
+
disclosures without collecting. Fast is the Lookup default. Deep adds the
|
|
61
|
+
applicable registration, DNS, HTTP, TLS, page, technology and network context.
|
|
62
|
+
Optional browser providers are not implicit CLI actions.
|
|
63
|
+
|
|
64
|
+
`dnssec-validate` and `mail-transport` are isolated authorised actions. Both
|
|
65
|
+
require a selected literal public resolver, a local trust-anchor document and
|
|
66
|
+
`--owned-or-authorized`; mail transport also requires `--active-probe`. Mail
|
|
67
|
+
transport handles at most three selected MX hosts sequentially, sends `EHLO`
|
|
68
|
+
and uses `STARTTLS` only when advertised. It does not send mail, authenticate,
|
|
69
|
+
test relay, enumerate recipients or retry automatically. DNSSEC, TLSA/DANE,
|
|
70
|
+
PKIX, STARTTLS and SMTP transport remain separate evidence states.
|
|
71
|
+
|
|
72
|
+
The repository-only rendered-capture package is outside hosted and distributable
|
|
73
|
+
collection. It executes remote page JavaScript only for an explicitly
|
|
74
|
+
authorised route set, and each admitted resource operator receives the exact
|
|
75
|
+
requested URL. Captures and screenshots remain local until the operator deletes
|
|
76
|
+
them.
|
|
77
|
+
|
|
78
|
+
## Files, output and automation
|
|
79
|
+
|
|
80
|
+
File inputs are bounded before parsing; directories, devices and named pipes are
|
|
81
|
+
refused. Output goes to the terminal unless a command supports `--output`.
|
|
82
|
+
Private output is written atomically and an existing path is refused unless
|
|
83
|
+
replacement is explicit.
|
|
84
|
+
|
|
85
|
+
Terminal text is the default. JSON, JSONL, CSV, Markdown, HTML and domain-only
|
|
86
|
+
formats are available only where the installed command declares them.
|
|
87
|
+
Redirected and machine output contains no ANSI or progress text. Diagnostics
|
|
88
|
+
and optional target-free `--events` output use standard error.
|
|
89
|
+
|
|
90
|
+
`--fail-on` and `--strict-exit` expose selected evidence states to automation
|
|
91
|
+
without changing the result document. Review focused help for the policies a
|
|
92
|
+
command supports.
|
|
400
93
|
|
|
401
94
|
| Code | Meaning |
|
|
402
95
|
| ---: | --- |
|
|
403
|
-
| 0 |
|
|
404
|
-
| 2 |
|
|
405
|
-
| 3 |
|
|
406
|
-
| 4 |
|
|
407
|
-
| 70 |
|
|
408
|
-
| 130 | The analyst cancelled
|
|
409
|
-
| 143 |
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
`
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
`
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
representative.
|
|
455
|
-
|
|
456
|
-
`registry-scaffold --profile <id> --suffix <suffix> --scenario <state>` emits
|
|
457
|
-
one bounded, sanitised synthetic fixture scaffold from the installed registry
|
|
458
|
-
catalogue. The three supported states are `registered`, `not_found`, and
|
|
459
|
-
`inconclusive`. It does not fetch a live response, include a real target, or
|
|
460
|
-
alter the embedded catalogue.
|
|
461
|
-
|
|
462
|
-
The offline RDAP supplied-evidence review implements the request shape defined
|
|
463
|
-
by RFC 9536 for `resources`, `domains`, `nameservers`, and `entities`. It also
|
|
464
|
-
validates a supplied server's `reverse_search_properties_mapping` response
|
|
465
|
-
before preparing a request. Only registered IANA property paths and exact
|
|
466
|
-
supported resource/property pairs are accepted. Preparing the request neither
|
|
467
|
-
proves that a particular server supports it nor sends a reverse search; active
|
|
468
|
-
execution remains gated on a reviewed server policy, privacy boundary, and
|
|
469
|
-
deterministic fixtures.
|
|
470
|
-
|
|
471
|
-
The separate maintenance command `npm run rdap-extensions:drift` compares the
|
|
472
|
-
pinned official RDAP extension fixture with the reviewed local interpretation
|
|
473
|
-
catalogue entirely offline. `--live` performs one bounded manual fetch from the
|
|
474
|
-
fixed official CSV URL and reports added, removed, renamed, status-changed,
|
|
475
|
-
unrecognized, and local-only identifiers. `--json` emits
|
|
476
|
-
`whoisleuth.rdap-extension-drift-audit` version 1. Drift exits with status 1 and
|
|
477
|
-
requires specification and fixture review; the command never enables an
|
|
478
|
-
extension, changes authority or availability logic, or issues reverse search.
|
|
479
|
-
|
|
480
|
-
`npm run service-dependencies:audit` validates the passive service-dependency
|
|
481
|
-
catalogue entirely offline. It checks the catalogue digest, duplicate
|
|
482
|
-
identifiers and target suffixes, evidence classes, source and licence
|
|
483
|
-
treatment, source dates, and a fixed 180-day review age. `--json` emits
|
|
484
|
-
`whoisleuth.service-dependency-signature-audit` version 1. A stale or changed
|
|
485
|
-
signature requires manual provider and benign-fixture review; the command
|
|
486
|
-
never resolves a target, checks an account, or tests claimability.
|
|
487
|
-
|
|
488
|
-
## Offline Risk calibration
|
|
489
|
-
|
|
490
|
-
`risk-calibrate` replays a versioned analyst-labelled fixture dataset through
|
|
491
|
-
the exact Risk model shared with the web application. It does not perform a
|
|
492
|
-
lookup, contact the hosted deployment, persist the dataset, alter model weights,
|
|
493
|
-
choose a threshold, or tune the model automatically. The report compares fixed
|
|
494
|
-
thresholds from 40 through 90 and identifies 70 as the current review band. It
|
|
495
|
-
also reports F1, balanced accuracy, Wilson 95% intervals, deliberately small
|
|
496
|
-
scan-depth and review-reason strata, and a current-versus-previous model replay.
|
|
497
|
-
Strata with fewer than 20 included labels are marked insufficient rather than
|
|
498
|
-
presented as reliable performance estimates.
|
|
499
|
-
|
|
500
|
-
The JSON report derives a bounded `interoperabilityTags` list from the
|
|
501
|
-
analyst-owned disposition and review reason. The mapping uses reviewed MISP
|
|
502
|
-
taxonomy terms only where the meaning is unambiguous. Tags do not change a
|
|
503
|
-
score, disposition, or case, and no MISP service is contacted.
|
|
504
|
-
|
|
505
|
-
Input is capped at 2 MiB and 500 records. Each record requires a unique bounded
|
|
506
|
-
ID, an ASCII DNS hostname, one existing analyst disposition, and a strict
|
|
507
|
-
whitelist of current scoring inputs. Unknown fields are discarded; arrays,
|
|
508
|
-
strings, ages, booleans, provider records, and external findings are revalidated
|
|
509
|
-
and bounded before scoring. The accepted dataset envelope is:
|
|
510
|
-
|
|
511
|
-
```json
|
|
512
|
-
{
|
|
513
|
-
"schema": "whoisleuth.risk-calibration-dataset",
|
|
514
|
-
"version": 2,
|
|
515
|
-
"records": [
|
|
516
|
-
{
|
|
517
|
-
"id": "fixture-1",
|
|
518
|
-
"domain": "login.example.test",
|
|
519
|
-
"analystDisposition": "confirmed_abuse",
|
|
520
|
-
"reviewReasonCode": "confirmed_credential_abuse",
|
|
521
|
-
"evidence": {
|
|
522
|
-
"availability": "registered",
|
|
523
|
-
"mutationTypes": ["dictionary"],
|
|
524
|
-
"hasPasswordField": true
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
]
|
|
528
|
-
}
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
`confirmed_abuse` is treated as a positive calibration label; `false_positive`
|
|
532
|
-
and `expected` are negative labels. `unreviewed`, `suspicious`, and
|
|
533
|
-
`closed_no_action` remain contextual and are excluded from threshold quality
|
|
534
|
-
metrics, as are records for which Risk is not applicable. Terminal output caps
|
|
535
|
-
its record list at 100 while `--json` retains the complete bounded report,
|
|
536
|
-
factor breakdowns, score bands, confidence intervals, bounded strata, model
|
|
537
|
-
comparison counts, and per-threshold confusion metrics. Analyst
|
|
538
|
-
dispositions and heuristic scores are review context: neither proves
|
|
539
|
-
maliciousness or safety.
|
|
540
|
-
|
|
541
|
-
The authenticated Monitor workspace can deliberately create the accepted
|
|
542
|
-
dataset from explicitly selected cases. Selection is available only when a case
|
|
543
|
-
has a reviewed disposition and retained normalised evidence. That local export
|
|
544
|
-
contains the case ID, domain, disposition, optional reviewed reason code, and a
|
|
545
|
-
bounded whitelist of current scoring inputs. A matched review-language signal
|
|
546
|
-
is exported as a fixed indicator, not as captured page text. It excludes notes,
|
|
547
|
-
tags, assertions, actions, contacts, raw
|
|
548
|
-
source data, provider payloads, and stored Risk scores. Before download, a local
|
|
549
|
-
review step shows the selected, included, and excluded counts, the domains and
|
|
550
|
-
dispositions that will be written, and the excluded evidence classes. The CLI
|
|
551
|
-
still validates every exported record and never trains, tunes, or changes the
|
|
552
|
-
Risk model.
|
|
553
|
-
|
|
554
|
-
## Lookalike review-yield calibration
|
|
555
|
-
|
|
556
|
-
`lookalike-calibrate [dataset.json]` summarises reviewed candidate outcomes by
|
|
557
|
-
mutation family without retaining domains, candidate identifiers, analyst
|
|
558
|
-
notes, or evidence values in its output. Input uses
|
|
559
|
-
`whoisleuth.lookalike-calibration-input` version 1, is capped at 2 MiB and 5,000
|
|
560
|
-
unique opaque records, and requires one reviewed disposition plus from 1 to 12
|
|
561
|
-
bounded mutation-family identifiers per record.
|
|
562
|
-
|
|
563
|
-
The report keeps exact disposition counts, review-lead rate, false-positive
|
|
564
|
-
rate, and a per-family sample state. Fewer than 20 reviewed observations remains
|
|
565
|
-
`insufficient`. The command is diagnostic only: it does not tune candidate
|
|
566
|
-
generation, filtering, ranking, or Risk, and a useful historical yield does not
|
|
567
|
-
establish that a current candidate is malicious or safe.
|
|
568
|
-
|
|
569
|
-
## Offline artefact verification
|
|
570
|
-
|
|
571
|
-
`verify-artifact` validates a supported local artefact without printing its
|
|
572
|
-
evidence contents. Input is capped at 15 MiB. It currently recognises ordinary
|
|
573
|
-
and encrypted workspace archives, case-response packets, acquisition-decision
|
|
574
|
-
exports, domain-comparison exports, Bulk mail-exposure exports, and Bulk review
|
|
575
|
-
manifests. Reviewed CLI case packs are checked against their canonical digest,
|
|
576
|
-
bounded browser-importable case collection, audience, and review marker. The
|
|
577
|
-
command also verifies the internal digests of a complete investigation
|
|
578
|
-
capsule, including its evidence, brief, graph, and optional analyst-record
|
|
579
|
-
projections, and that capsule can be passed to `sign-artifact`. It also validates the bounded versioned structure of saved CLI
|
|
580
|
-
Lookup JSON. Because saved Lookup documents do not embed a checksum or
|
|
581
|
-
signature, that result is reported as `structure_valid` with content integrity
|
|
582
|
-
explicitly unchecked. Saved Lookup validation retains its stricter 8 MiB
|
|
583
|
-
document ceiling.
|
|
584
|
-
|
|
585
|
-
For an ordinary workspace archive, the command validates the versioned
|
|
586
|
-
structure, section byte counts, record counts, and per-section checksums. For a
|
|
587
|
-
supported signed review artefact, it validates the declared SHA-256 digest. An
|
|
588
|
-
encrypted archive without `--passphrase-file` can establish only that the
|
|
589
|
-
envelope is structurally valid; it reports `envelope_valid` and explicitly
|
|
590
|
-
leaves authenticated encryption and inner checksums unchecked.
|
|
591
|
-
|
|
592
|
-
Supplying a separate passphrase file, capped at 1 KiB, allows authenticated
|
|
593
|
-
decryption followed by the ordinary workspace checks. The passphrase is never
|
|
594
|
-
accepted as a command-line value, printed, or retained. Verification detects
|
|
595
|
-
changes against the artefact's declared contract; it does not authenticate the
|
|
596
|
-
analyst or establish that an observation was accurate or remains current.
|
|
597
|
-
|
|
598
|
-
## Privacy-safe source reliability report
|
|
599
|
-
|
|
600
|
-
`source-report` summarises source states, durations, truncation, and rate-limit
|
|
601
|
-
counts from one version-1 CLI Lookup, Bulk, or Bulk-item document, a JSON array
|
|
602
|
-
of up to 100 such documents, or an array containing only previously generated
|
|
603
|
-
source-reliability reports. Lookup documents and reports cannot be mixed.
|
|
604
|
-
Merged reports preserve exact state and sample totals and add bounded ranges
|
|
605
|
-
for each input report's median and p95 duration, a bounded source timeline,
|
|
606
|
-
fast/deep/unknown cohorts, and the earliest and latest valid report generation
|
|
607
|
-
times. Exact duplicate reports are rejected so one saved report is not
|
|
608
|
-
accidentally counted twice. Per-source failure, partial, truncation, and
|
|
609
|
-
rate-limit rates remain separate. The command does not pretend that aggregate
|
|
610
|
-
timing distributions can reconstruct the original target-level samples. Input
|
|
611
|
-
is capped at 12 MiB and traversal, source, duration, and output counts are
|
|
612
|
-
bounded.
|
|
613
|
-
|
|
614
|
-
The report retains only fixed source identifiers and aggregate operational
|
|
615
|
-
counts. It does not output targets, queries, endpoints, source limitations, raw
|
|
616
|
-
evidence, or provider payloads. Observation-envelope duration and the
|
|
617
|
-
potentially overlapping Lookup timing are reported separately and never added
|
|
618
|
-
together. It is a local engineering diagnostic, not analytics, a source-quality
|
|
619
|
-
score, or evidence that a collector is currently healthy.
|
|
620
|
-
|
|
621
|
-
## Workspace archive inspection
|
|
622
|
-
|
|
623
|
-
`inspect-archive` verifies an ordinary or encrypted workspace archive and then
|
|
624
|
-
reports its versioned sections, counts, byte sizes, and checksum states without
|
|
625
|
-
printing stored records. An encrypted archive requires
|
|
626
|
-
`--passphrase-file`; passphrases are never accepted on the command line.
|
|
627
|
-
|
|
628
|
-
An optional `--search` is exact and case-insensitive across a fixed allowlist
|
|
629
|
-
of target fields. Default matches disclose only the section, field name, and a
|
|
630
|
-
SHA-256 digest. `--reveal` must be selected explicitly to print the matched
|
|
631
|
-
value. Notes, contacts, raw evidence, arbitrary object fields, and partial text
|
|
632
|
-
search are excluded. Unicode domain searches are canonicalized to their
|
|
633
|
-
DNS-safe ASCII form before exact comparison. `--require-match` makes a
|
|
634
|
-
no-match result fail for automation and is valid only with `--search`.
|
|
635
|
-
Traversal, input size, matches, depth, arrays, and strings are bounded.
|
|
636
|
-
|
|
637
|
-
Version 2 of the inspection report adds a content digest over the ordered
|
|
638
|
-
section identifiers, schema versions, record counts, and normalised section
|
|
639
|
-
content. It deliberately excludes JSON formatting and each section envelope's
|
|
640
|
-
export time, so two separately exported archives with the same retained
|
|
641
|
-
workspace content have the same identity. `--expect-content-digest <sha256:digest>`
|
|
642
|
-
fails when that identity differs, which supports deliberate transfer checks
|
|
643
|
-
without printing records. Matching digests detect equivalent retained content;
|
|
644
|
-
they do not authenticate who created it or establish that its evidence is
|
|
645
|
-
accurate or current. The report separately identifies the source archive
|
|
646
|
-
version and the installed reader version.
|
|
647
|
-
|
|
648
|
-
## Optional evidence-package signing
|
|
649
|
-
|
|
650
|
-
`sign-artifact` signs a locally verified case-response packet or supported
|
|
651
|
-
review manifest with an externally managed Ed25519 private key:
|
|
652
|
-
|
|
653
|
-
```bash
|
|
654
|
-
node bin/whoisleuth.mts sign-artifact packet.json --private-key-file analyst-private.pem > packet.signed.json
|
|
655
|
-
node bin/whoisleuth.mts verify-signature packet.signed.json --public-key-file analyst-public.pem
|
|
656
|
-
```
|
|
657
|
-
|
|
658
|
-
The signed package embeds the public key, key identifier, signature time, and
|
|
659
|
-
original artefact. Verification first checks the exact package field set and
|
|
660
|
-
signature, then the artefact's own checksums or manifest. A result is reported
|
|
661
|
-
as `signature_valid`; signer trust is separately reported as `trusted_key` or
|
|
662
|
-
`embedded_key_only`. Without a separately supplied trusted public key,
|
|
663
|
-
verification establishes only that the package is internally self-consistent.
|
|
664
|
-
WHOISleuth does not generate, store, recover, rotate, publish, or establish
|
|
665
|
-
trust in signing keys.
|
|
666
|
-
|
|
667
|
-
## Reproducible investigation manifest
|
|
668
|
-
|
|
669
|
-
`manifest <artefact.json> [...] --workflow <label>` reads from 1 to 16 ordered
|
|
670
|
-
JSON artefacts and emits `whoisleuth.investigation-manifest` version 1. Each
|
|
671
|
-
entry records its sequence, bounded schema and version metadata, exact UTF-8
|
|
672
|
-
content digest, canonical JSON digest, and byte count. The manifest also records
|
|
673
|
-
the installed CLI version and can include an externally calculated
|
|
674
|
-
`--configuration-digest sha256:...` without copying configuration values.
|
|
675
|
-
|
|
676
|
-
Source paths, filenames, command-line arguments, and artefact contents are not
|
|
677
|
-
retained. Individual artefacts are capped at 15 MiB and the ordered set at
|
|
678
|
-
32 MiB. The manifest carries its own canonical integrity digest, works with
|
|
679
|
-
`verify-artifact`, and can be passed to `sign-artifact`. Reproduction still
|
|
680
|
-
requires the exact digested artefacts, compatible source services, and any
|
|
681
|
-
separately held configuration; matching digests do not establish observation
|
|
682
|
-
accuracy or freshness.
|
|
683
|
-
|
|
684
|
-
## Bulk lookup
|
|
685
|
-
|
|
686
|
-
`bulk` accepts a newline-delimited file or stdin. It preserves input order,
|
|
687
|
-
removes case-insensitive duplicates, and returns a result for every retained
|
|
688
|
-
query. Input is capped at 1 MiB. Fast mode is capped at 500 queries with four
|
|
689
|
-
workers by default. Deep mode is capped at 50 queries with two workers by
|
|
690
|
-
default. Explicit concurrency cannot exceed eight in fast mode or three in
|
|
691
|
-
deep mode.
|
|
692
|
-
|
|
693
|
-
Bulk uses the shared compact lookup response, so it does not retain raw RDAP
|
|
694
|
-
objects or WHOIS response bodies. `--json` returns one bounded collection;
|
|
695
|
-
`--jsonl` emits one self-contained versioned item per line. `--domains` emits
|
|
696
|
-
only successfully normalised domain names, while `--queries` preserves the
|
|
697
|
-
selected bounded input queries and is suitable for an exact retry queue.
|
|
698
|
-
Version 2 adds a
|
|
699
|
-
bounded `dnsSummary` projection for observed A, AAAA, NS, and MX records plus
|
|
700
|
-
null MX, SPF, and DMARC state. `--csv` writes fixed columns for automation,
|
|
701
|
-
including the DNS summaries and explicit outcome.
|
|
702
|
-
|
|
703
|
-
`--registered-only`, `--inconclusive-only`, and `--errors-only` are mutually
|
|
704
|
-
exclusive output filters. The first retains registered, for-sale, and expiring
|
|
705
|
-
authority-aware states. The second retains unknown authority states and failed
|
|
706
|
-
rows. The third retains only rows whose lookup operation failed, which is useful
|
|
707
|
-
for producing an exact retry queue without treating an inconclusive successful
|
|
708
|
-
lookup as an operational error. Filtering does not change collection and never
|
|
709
|
-
converts an unavailable or failed source into an unregistered result. Machine
|
|
710
|
-
documents record collected and emitted counts. A mixture of successful and
|
|
711
|
-
failed queries exits with code 4 while preserving every collected result before
|
|
712
|
-
output filtering. For example, `bulk domains.txt --queries --errors-only`
|
|
713
|
-
produces only the exact failed inputs while retaining the partial-failure exit.
|
|
714
|
-
|
|
715
|
-
## Certificate Transparency search
|
|
716
|
-
|
|
717
|
-
`ct-search` accepts one keyword as an argument or on stdin and calls the same
|
|
718
|
-
bounded Certificate Transparency module as the web application. It contacts
|
|
719
|
-
the upstream public log search service directly from the local machine; it
|
|
720
|
-
does not call the hosted WHOISleuth deployment. Quote a multi-word keyword so
|
|
721
|
-
the shell passes it as one argument.
|
|
722
|
-
|
|
723
|
-
Terminal output summarises certificate rows, observed hostnames, canonical
|
|
724
|
-
registrable-domain matches, observation times, bounded certificate-issuance
|
|
725
|
-
groups, and completeness. An issuance group contains names observed together
|
|
726
|
-
in one public certificate record; a cross-domain group is a review lead, not
|
|
727
|
-
an attribution or ownership finding. Terminal output shows at most 100 matches
|
|
728
|
-
and five hostnames per match, with explicit omission notes. `--json` returns
|
|
729
|
-
the complete bounded structured result in the versioned
|
|
730
|
-
`whoisleuth.cli.ct-search` schema. The certificate-group cap is reported
|
|
731
|
-
separately from the registrable-domain result cap. CT observations do not prove
|
|
732
|
-
that a website is active or malicious.
|
|
733
|
-
|
|
734
|
-
## Local certificate event intake
|
|
735
|
-
|
|
736
|
-
`ct-intake [events.json]` reads `whoisleuth.ct-event-batch` version 1 entirely
|
|
737
|
-
offline. Each source-qualified event supplies a log identifier, observation
|
|
738
|
-
time, certificate SHA-256 digest, one or more DNS names, completeness, and
|
|
739
|
-
optional issuer, expiry, and limitations. Unknown fields, malformed names,
|
|
740
|
-
unsupported completeness values, and oversized batches are rejected.
|
|
741
|
-
|
|
742
|
-
JSON output uses the existing `whoisleuth.external-findings` version 3 contract
|
|
743
|
-
and can be deliberately imported into the browser Console. Wildcard names are
|
|
744
|
-
normalised to their base DNS name, exact event/domain duplicates are removed,
|
|
745
|
-
and deterministic output is capped at 100 findings, 25 domains, and 20 findings
|
|
746
|
-
per domain to match the browser import boundary. Omission is stated in each
|
|
747
|
-
retained finding when the supplied batch exceeds those limits. The command
|
|
748
|
-
makes no request and treats every certificate event as a review lead, not proof
|
|
749
|
-
that the certificate was served, requested, or controlled by the named domain.
|
|
750
|
-
|
|
751
|
-
## Declarative observation interchange
|
|
752
|
-
|
|
753
|
-
`map-observations [mapping.json]` reads
|
|
754
|
-
`whoisleuth.external-observation-mapping` version 1 and applies one strict,
|
|
755
|
-
declarative profile to at most 500 local records. The profile selects bounded
|
|
756
|
-
dotted field paths for the domain, summary, observation time, optional
|
|
757
|
-
reference, and optional completeness. It fixes one source, evidence class, and
|
|
758
|
-
finding category for the batch. Profiles cannot contain scripts, templates,
|
|
759
|
-
computed expressions, network endpoints, or executable callbacks. Prototype
|
|
760
|
-
paths and unknown fields are rejected.
|
|
761
|
-
|
|
762
|
-
The resulting JSON is the existing browser-compatible
|
|
763
|
-
`whoisleuth.external-findings` version 3 contract. It retains source identity,
|
|
764
|
-
observation time, completeness, and limitations, while stating that field
|
|
765
|
-
semantics were not independently verified. Deterministic output is capped at
|
|
766
|
-
100 findings, 25 domains, and 20 findings per domain. The command makes no
|
|
767
|
-
request and never interprets an omitted field as a negative observation.
|
|
768
|
-
|
|
769
|
-
`oam-export [external-findings.json]` projects that strict findings document
|
|
770
|
-
into `whoisleuth.open-asset-model-bridge` version 1. It uses the documented
|
|
771
|
-
[OWASP Open Asset Model](https://github.com/owasp-amass/open-asset-model)
|
|
772
|
-
vocabulary for bounded `FQDN`, `IPAddress`, and `TLSCertificate` assets plus
|
|
773
|
-
`dns_record` and `san_dns_name` relations. Only typed A, AAAA, and SHA-256
|
|
774
|
-
certificate observations create infrastructure assets or relations. Other
|
|
775
|
-
findings remain represented by their FQDN asset.
|
|
776
|
-
|
|
777
|
-
This bridge wrapper is not a claim that every receiving implementation accepts
|
|
778
|
-
one universal native serialisation. Receivers must validate the projection
|
|
779
|
-
against their supported model version. WHOISleuth preserves source and
|
|
780
|
-
completeness as discovery metadata, does not invent a confidence score, and
|
|
781
|
-
does not treat an edge as proof of ownership, control, coordination, intent,
|
|
782
|
-
safety, or maliciousness.
|
|
783
|
-
|
|
784
|
-
## Lookalike discovery
|
|
785
|
-
|
|
786
|
-
`discover` runs the same pure, bounded lookalike generator as the Discover
|
|
787
|
-
tool without making network requests. It accepts a brand label or a
|
|
788
|
-
domain with one suffix label. The default TLD set is `com,net,org`; replace it
|
|
789
|
-
with `--tlds com,net` when narrower coverage is wanted.
|
|
790
|
-
|
|
791
|
-
Generation presets are `common`, `impersonation`, and `all` (the default).
|
|
792
|
-
Keyboard-aware mutations support `qwerty` (the default), `azerty`, and
|
|
793
|
-
`qwertz`; `--keyboard all` uses their bounded combined neighbour set, including
|
|
794
|
-
adjacent number-row keys. Supply a UTF-8 text file with
|
|
795
|
-
`--dictionary terms.txt` to add up to 100 local terms when
|
|
796
|
-
using the `impersonation` or `all` preset. Dictionary input is capped at 4,096
|
|
797
|
-
bytes and individual terms at 32 characters. Machine output records accepted
|
|
798
|
-
and rejected term counts but never copies the private terms into its metadata.
|
|
799
|
-
|
|
800
|
-
Use `--families <ids>` instead of `--preset` to run an exact comma-separated
|
|
801
|
-
selection. Supported IDs are `character_addition`, `character_omission`,
|
|
802
|
-
`character_duplication`, `character_transposition`, `pluralization`,
|
|
803
|
-
`tld_embedding`, `www_prefix`, `hyphenation`, `separator_omission`,
|
|
804
|
-
`word_reordering`, `keyboard_substitution`, `keyboard_insertion`, `vowel_swap`,
|
|
805
|
-
`bitsquatting`, `ascii_homoglyph`, `unicode_homoglyph`,
|
|
806
|
-
`unicode_whole_label`, `unicode_homoglyph_depth_2`, `dictionary`,
|
|
807
|
-
`dictionary_token_replacement`, `tld_typo`, and `tld_substitution`. Machine
|
|
808
|
-
output records the normalised custom selection. A custom dictionary file
|
|
809
|
-
requires `dictionary` or `dictionary_token_replacement` in that selection.
|
|
810
|
-
|
|
811
|
-
`--domains` writes the unique candidate names only. `--snapshot <file>` keeps
|
|
812
|
-
one private, versioned local observation of the normalised seed, generation
|
|
813
|
-
configuration, custom-dictionary digest, and candidate set. The first run
|
|
814
|
-
creates the snapshot; later runs report added and removed candidates before
|
|
815
|
-
atomically replacing it. The snapshot never stores private dictionary terms.
|
|
816
|
-
Use the same command from a local scheduler such as cron or a system timer to
|
|
817
|
-
perform repeatable discovery runs. WHOISleuth does not install a scheduler,
|
|
818
|
-
run a background daemon, or infer that an added candidate is registered,
|
|
819
|
-
active, available, or malicious.
|
|
820
|
-
|
|
821
|
-
Dotted subdomain permutations are intentionally excluded because the lookup
|
|
822
|
-
pipeline validates a hostname's registrable parent. The CLI does not present
|
|
823
|
-
authoritative parent registration evidence as proof that a generated hostname
|
|
824
|
-
exists.
|
|
825
|
-
|
|
826
|
-
Terminal output is capped at 200 candidates with an explicit notice. Versioned
|
|
827
|
-
JSON and JSONL use `whoisleuth.cli.discover` schema version 2 and retain the
|
|
828
|
-
complete bounded candidate set and mutation provenance. Internationalised
|
|
829
|
-
candidates show the DNS-safe ASCII form and readable Unicode form together in
|
|
830
|
-
terminal output. The Impersonation and All presets can add up to six
|
|
831
|
-
deterministic whole-label Unicode candidates when every letter has a reviewed
|
|
832
|
-
same-script replacement. The command generates candidates only. It does not
|
|
833
|
-
claim that a domain is registered, active, or malicious.
|
|
834
|
-
|
|
835
|
-
`unicode_homoglyph_depth_2` is an explicit `--families` option and is never
|
|
836
|
-
enabled by a preset. It replaces exactly two ASCII letters with characters
|
|
837
|
-
from the same reviewed script, ranks curated mappings first, and returns at
|
|
838
|
-
most 256 candidates. JSON and terminal output report generated candidates,
|
|
839
|
-
cross-script or invalid combinations omitted by policy, and lower-ranked
|
|
840
|
-
label variants omitted by the family or overall generation budget.
|
|
841
|
-
|
|
842
|
-
## Supervised candidate scan
|
|
843
|
-
|
|
844
|
-
`discover-scan` composes the same bounded generator with the compact Lookup
|
|
845
|
-
collector. Unlike `discover`, it is an explicitly networked command. It selects
|
|
846
|
-
the first deterministic candidates up to `--scan-limit`, processes fixed
|
|
847
|
-
chunks sequentially, and retains each registration and DNS source state. Fast
|
|
848
|
-
mode is the default and accepts at most 500 candidates. Explicit `--deep` mode
|
|
849
|
-
is capped at 50 candidates and concurrency 3 because it can add WHOIS, DNS,
|
|
850
|
-
HTTP, TLS, page, and technology work for every selected candidate.
|
|
851
|
-
|
|
852
|
-
Use `--chunk-size 1-100`, `--concurrency 1-8`, and the existing private
|
|
853
|
-
`--checkpoint <file> [--resume]` boundary to control a run. The checkpoint is
|
|
854
|
-
tied to the exact ordered candidate set and scan mode. A new generation order,
|
|
855
|
-
limit, or mode requires another checkpoint. `--resolver` accepts at most three
|
|
856
|
-
literal IPv4 or IPv6 recursive-resolver addresses and applies them only to DNS
|
|
857
|
-
observations in this local run. Resolver hostnames and automatic third-party
|
|
858
|
-
resolver selection are not supported. The selected resolvers can observe the
|
|
859
|
-
queried candidates and may apply their own logging and retention policies.
|
|
860
|
-
|
|
861
|
-
An optional newline-delimited `--allowlist` accepts at most 500 domains and 64
|
|
862
|
-
KiB. Matching candidates remain in evidence and are labelled `suppressed` in
|
|
863
|
-
the review queue; the full list and unmatched entries are not copied into
|
|
864
|
-
output, while each matching scanned candidate necessarily exposes that match.
|
|
865
|
-
Allowlisting never deletes a result or asserts that it is safe. Output filters
|
|
866
|
-
select registered, inconclusive, acquisition-review, or
|
|
867
|
-
suppressed rows without changing whole-run counts or source health. JSON,
|
|
868
|
-
JSONL, CSV, and domain-list forms retain mutation provenance and explicit
|
|
869
|
-
review lanes. The queue provides next manual actions, not automatic lookup,
|
|
870
|
-
acquisition, blocking, submission, or enforcement.
|
|
871
|
-
|
|
872
|
-
Deep compact results can group exact shared addresses, nameservers, and mail
|
|
873
|
-
servers observed across at least two candidates. These bounded relationships
|
|
874
|
-
are pivot leads only. Common hosting, delivery, registrar, and mail services
|
|
875
|
-
can produce the same relationship without common ownership or control.
|
|
876
|
-
|
|
877
|
-
`--observation-snapshot <file>` keeps a private versioned local projection of
|
|
878
|
-
registration state, confidence, and bounded A, AAAA, NS, MX, null-MX, SPF, and
|
|
879
|
-
DMARC summaries for the exact candidate set, mode, and resolver selection.
|
|
880
|
-
Version 2 records registration and DNS observation times and latest component
|
|
881
|
-
states separately; version 1 is read and normalised on the next write. A later
|
|
882
|
-
identical run reports material field changes only for components collected
|
|
883
|
-
with enough completeness to support the comparison. If registration or DNS is
|
|
884
|
-
partial or unavailable, the prior usable evidence for that component is
|
|
885
|
-
preserved and the attempt is reported as unavailable rather than converting
|
|
886
|
-
missing data into a removal. Raw registry
|
|
887
|
-
records, contacts, page content, and request details are excluded. Snapshot
|
|
888
|
-
differences are review prompts, not proof of ownership, control, intent,
|
|
889
|
-
safety, or maliciousness.
|
|
890
|
-
|
|
891
|
-
## Domain posture audit
|
|
892
|
-
|
|
893
|
-
`posture` runs the standard-profile form of the owned-domain DNS and
|
|
894
|
-
email-security audit used by Brand Profiles. It queries registry status and
|
|
895
|
-
DNSSEC evidence, nameserver delegation, SPF, DMARC, MX, CAA, MTA-STS, TLS-RPT,
|
|
896
|
-
and BIMI directly from the local machine. Literal SPF include and redirect
|
|
897
|
-
branches are expanded within fixed depth, policy-query, DNS-term, void-answer,
|
|
898
|
-
cycle, and time bounds. External DMARC reporting authorisation and external
|
|
899
|
-
nameserver, mail, SPF, and reporting dependencies are separately reported.
|
|
900
|
-
Supply up to ten known active and retired DKIM selectors in total with
|
|
901
|
-
`--selectors selector1,selector2` and `--retired-selectors selector0`;
|
|
902
|
-
selectors cannot be reliably discovered from DNS, so no-selector output
|
|
903
|
-
reports DKIM as not checked. Use `--mail-profile standard`,
|
|
904
|
-
`--mail-profile defensive-no-mail`, or `--mail-profile parked` to make the
|
|
905
|
-
intended mail posture explicit rather than inferring it from DNS.
|
|
906
|
-
|
|
907
|
-
Terminal output shows each pass, review, action, or informational result and
|
|
908
|
-
caps displayed records at five per check with an explicit omission notice.
|
|
909
|
-
Versioned JSON retains the complete bounded report, including SPF traversal,
|
|
910
|
-
DMARC authorisation, and dependency provenance. Warnings and dangers are
|
|
911
|
-
findings rather than command failures; transient resolver or policy-fetch
|
|
912
|
-
failures remain informational and should be retried before changing DNS.
|
|
913
|
-
|
|
914
|
-
## HTTP intelligence
|
|
915
|
-
|
|
916
|
-
`http` runs the same bounded safe homepage probe used by a deep lookup. It
|
|
917
|
-
tries HTTPS before HTTP, follows only validated public-network redirects, caps
|
|
918
|
-
each attempt at six seconds, and captures at most 300,000 response bytes for
|
|
919
|
-
hashing and metadata. A non-success HTTP response still proves that a web
|
|
920
|
-
service answered; failure of both schemes remains inconclusive rather than
|
|
921
|
-
evidence that no website exists.
|
|
922
|
-
|
|
923
|
-
The command reports normalised redirect, response, content, selected security-
|
|
924
|
-
header, body-hash, completeness, and attempt provenance. Captured homepage text
|
|
925
|
-
is never written to terminal or JSON output. Query strings are removed by the
|
|
926
|
-
shared HTTP evidence normalizer, and terminal values are additionally bounded
|
|
927
|
-
and control-safe.
|
|
928
|
-
|
|
929
|
-
## TLS intelligence
|
|
930
|
-
|
|
931
|
-
`tls` runs the same bounded one-connection TLS collector used by deep lookups.
|
|
932
|
-
It resolves the hostname once through the public-address guard, validates every
|
|
933
|
-
answer, connects directly to the first validated address on port 443, and keeps
|
|
934
|
-
the original hostname for SNI and certificate identity checking. Resolution
|
|
935
|
-
and handshake work share a five-second deadline.
|
|
936
|
-
|
|
937
|
-
The report retains the negotiated protocol, ALPN and cipher, runtime trust and
|
|
938
|
-
hostname checks, certificate validity, bounded subject and issuer names, SANs,
|
|
939
|
-
SAN class counts, signature algorithm and OID, extended-key-usage purposes,
|
|
940
|
-
classified Authority Information Access presence counts, SHA-256 certificate
|
|
941
|
-
and public-key fingerprints, a bounded certificate chain, and neutral
|
|
942
|
-
findings. AIA responder and issuer locations are classified as HTTP, HTTPS, or
|
|
943
|
-
other and then discarded; they are not retained or followed. The collector
|
|
944
|
-
stores no certificate bytes, session material, or application data and does
|
|
945
|
-
not enumerate supported protocol or cipher suites.
|
|
946
|
-
A failed collection is inconclusive rather than proof that no TLS service
|
|
947
|
-
exists.
|
|
948
|
-
|
|
949
|
-
## Registry-source comparison
|
|
950
|
-
|
|
951
|
-
`compare` reads one version-1 `whoisleuth.cli.lookup` domain document from a
|
|
952
|
-
file or stdin and emits a version-3 `whoisleuth.cli.compare` document. Its
|
|
953
|
-
primary comparison reconciles normalised registry RDAP and WHOIS fields. When
|
|
954
|
-
the saved deep lookup also represents the optional registrar RDAP follow-up,
|
|
955
|
-
an additional sibling comparison reconciles the portable registry and
|
|
956
|
-
registrar RDAP publication fields. The command does not repeat the lookup,
|
|
957
|
-
contact the hosted deployment, or treat a conflict as a command failure. Use a
|
|
958
|
-
deep lookup when multiple sources are wanted; a fast lookup deliberately
|
|
959
|
-
records WHOIS as skipped, and comparison preserves that state as unavailable
|
|
960
|
-
rather than misreporting RDAP-only publication.
|
|
961
|
-
|
|
962
|
-
Input is capped at 8 MiB and must retain the lookup schema, mode, source
|
|
963
|
-
diagnostics, and normalised parsed source sections. Per-value, list, and event
|
|
964
|
-
bounds are revalidated because saved JSON is treated as untrusted input. A
|
|
965
|
-
successful registrar source must include a normalised object and agree with
|
|
966
|
-
its diagnostic status. Raw RDAP JSON, registrar contacts and source-specific
|
|
967
|
-
handles, WHOIS response bodies, availability evidence, and unrelated lookup
|
|
968
|
-
fields are not copied into the comparison result.
|
|
969
|
-
|
|
970
|
-
When the saved Lookup contains valid version-5, version-6, or version-7, context-only
|
|
971
|
-
registry-access diagnostics, version 3 retains their bounded suffix, access profiles, and
|
|
972
|
-
limitation. Terminal output labels the same collection context explicitly.
|
|
973
|
-
It explains source reachability only and cannot decide registration,
|
|
974
|
-
availability, ownership, safety, or maliciousness. Older documents and saved
|
|
975
|
-
lookups without that context do not gain a registry-access field.
|
|
976
|
-
|
|
977
|
-
Terminal and versioned JSON output cover domain identity, registry object ID,
|
|
978
|
-
registrar, registrar IANA ID, lifecycle dates, DNSSEC, statuses, and name
|
|
979
|
-
servers. The shared comparison model normalises harmless case, punctuation,
|
|
980
|
-
ordering, and date-precision differences while distinguishing conflicts,
|
|
981
|
-
one-source publication, redaction, incomplete sources, and unavailable
|
|
982
|
-
sources. This is source reconciliation, not an availability, ownership, or
|
|
983
|
-
maliciousness decision.
|
|
984
|
-
|
|
985
|
-
## Static page comparison
|
|
986
|
-
|
|
987
|
-
`page-compare <left.json> <right.json>` reads two different version-1 saved
|
|
988
|
-
Deep domain Lookup documents and compares the already-retained static page
|
|
989
|
-
identity, exact and perceptual favicon evidence, technology identifiers, TLS
|
|
990
|
-
issuer label, and TLS public-key fingerprint. DOM structure is compared first
|
|
991
|
-
by its exact bounded tag-sequence digest, then, when both captures provide it,
|
|
992
|
-
by a parse5-tokenized structural SimHash. It makes no request and requires
|
|
993
|
-
complete supported static page-identity observations on both sides.
|
|
994
|
-
|
|
995
|
-
Each page component remains independent. Exact, similar, overlapping,
|
|
996
|
-
different, unavailable, and partial evidence are not collapsed into a score.
|
|
997
|
-
Matching components are investigative relationships rather than proof of
|
|
998
|
-
copying, common ownership, control, intent, safety, or maliciousness. Static
|
|
999
|
-
comparison does not execute JavaScript; use the optional local rendered
|
|
1000
|
-
capture package only when that additional active behaviour is authorised.
|
|
1001
|
-
|
|
1002
|
-
## Passive mail exposure review
|
|
1003
|
-
|
|
1004
|
-
`mail-review [bulk.json|bulk.jsonl]` reads version-2 Bulk output locally and
|
|
1005
|
-
summarises MX, null MX, SPF, DMARC, and mail-provider relationships. It keeps
|
|
1006
|
-
authenticated mail, authentication gaps, incomplete authentication evidence,
|
|
1007
|
-
no explicit MX, null MX, and incomplete DNS evidence as separate states.
|
|
1008
|
-
Shared-provider relationships are based only on the registrable domain of an
|
|
1009
|
-
observed MX hostname and do not establish shared ownership or control.
|
|
1010
|
-
|
|
1011
|
-
The command makes no DNS or SMTP request and retains no source path. It does
|
|
1012
|
-
not test message acceptance, relay behaviour, mailbox existence, catch-all
|
|
1013
|
-
behaviour, SMTP banners, or whether a mail server is rogue, safe, or malicious.
|
|
1014
|
-
|
|
1015
|
-
An analyst may add a bounded `tlsaEvidence` object to a version-2 Bulk item for
|
|
1016
|
-
offline DANE review. It must name the exact `_25._tcp.<mx-host>` service, and
|
|
1017
|
-
that host must occur in the same item's retained MX evidence. A certificate
|
|
1018
|
-
association match is complete only when `dnssecState` is `validated`. TLSA
|
|
1019
|
-
usages 0 and 1 additionally require `pkixValidationState: "validated"`.
|
|
1020
|
-
Usages 0 and 2 compare against the bounded `authorityMaterials` array; usages
|
|
1021
|
-
1 and 3 compare against the supplied leaf certificate or SPKI. Mismatched
|
|
1022
|
-
service names, missing certificate roles, unvalidated prerequisites, malformed
|
|
1023
|
-
material, and truncation remain invalid, partial, or untrusted rather than
|
|
1024
|
-
becoming a DANE match.
|
|
1025
|
-
|
|
1026
|
-
## Offline supplied-evidence review
|
|
1027
|
-
|
|
1028
|
-
`review-evidence [evidence.json]` accepts one version-1 JSON input and performs
|
|
1029
|
-
only deterministic local parsing, comparison, or request planning. Input is
|
|
1030
|
-
capped at 16 MiB. The command never retrieves DNS, opens SMTP, contacts an
|
|
1031
|
-
RDAP server, submits a resolver query, or looks up an address in a hosted
|
|
1032
|
-
GeoIP service.
|
|
1033
|
-
|
|
1034
|
-
Supported input schemas are:
|
|
1035
|
-
|
|
1036
|
-
- `whoisleuth.dnssec-evidence-input`: compares bounded DS and DNSKEY records,
|
|
1037
|
-
recalculates DNSKEY key tags and supported DS digests, and reviews supplied
|
|
1038
|
-
RRSIG validity windows at `observedAt`. `consistent` describes only the
|
|
1039
|
-
supplied DS/DNSKEY relationship. It does not authenticate a chain to a root
|
|
1040
|
-
trust anchor, validate RRSIG cryptography, or prove that a missing record is
|
|
1041
|
-
absent.
|
|
1042
|
-
- `whoisleuth.tlsa-evidence-input`: binds TLSA records to one explicit
|
|
1043
|
-
`_port._transport.hostname` service and compares supplied leaf or authority
|
|
1044
|
-
certificate/SPKI bytes. `matched` requires independently validated DNSSEC;
|
|
1045
|
-
PKIX-TA and PKIX-EE usages also require an independently validated PKIX path.
|
|
1046
|
-
The command does not retrieve the certificate or negotiate STARTTLS.
|
|
1047
|
-
- `whoisleuth.rdap-search-input`: normalises a supplied RDAP search-help
|
|
1048
|
-
response and prepares an exact supported reverse-search request without
|
|
1049
|
-
sending it. If the document also contains a previously obtained `response`,
|
|
1050
|
-
the command checks its bounded property mappings against the reviewed
|
|
1051
|
-
registration and reports omitted or unrecognised mappings without treating
|
|
1052
|
-
the response as authoritative or complete.
|
|
1053
|
-
- `whoisleuth.rpki-route-input`: compares a route prefix and origin ASN with a
|
|
1054
|
-
bounded analyst-supplied VRP set.
|
|
1055
|
-
- `whoisleuth.local-geoip-query`: queries an analyst-supplied bounded prefix
|
|
1056
|
-
database whose source, version, and licence metadata remain in the result.
|
|
1057
|
-
- `whoisleuth.local-mmdb-query`: with an explicit `--mmdb <database-file>`,
|
|
1058
|
-
queries one analyst-supplied MaxMind DB file locally. The query document must
|
|
1059
|
-
carry `address`, `sourceLabel`, `databaseVersion`, and `license`. WHOISleuth
|
|
1060
|
-
does not bundle, download, update, license, transmit, or retain the database.
|
|
1061
|
-
The nested result uses the same address, network, country, region, city, ASN,
|
|
1062
|
-
source, and limitation fields as the bounded JSON-prefix path. This mode is
|
|
1063
|
-
CLI-only because a hosted or browser deployment cannot open an analyst's
|
|
1064
|
-
local file; its JSON result remains portable to website-compatible evidence
|
|
1065
|
-
archives and reports.
|
|
1066
|
-
- `whoisleuth.encrypted-dns-plan-input`: validates an explicitly reviewed
|
|
1067
|
-
encrypted-DNS provider contract and prepares a bounded query plan. It does
|
|
1068
|
-
not execute the plan.
|
|
1069
|
-
- `whoisleuth.zone-intent.input`: parses either a deliberately supported,
|
|
1070
|
-
bounded BIND master-file subset or normalised DNS records and compares it
|
|
1071
|
-
with one separately attributed observation. TXT values are reduced to
|
|
1072
|
-
SHA-256 digests, unsupported directives and records remain rejected, and an
|
|
1073
|
-
incomplete observation never becomes a missing-record conclusion. The
|
|
1074
|
-
review does not contact a resolver or apply a DNS change.
|
|
1075
|
-
- `whoisleuth.domain-portfolio.input`: reviews up to 500 analyst-supplied
|
|
1076
|
-
domain inventory rows for exact registrar, DNS, mail, certificate and
|
|
1077
|
-
recovery concentration, renewal-review gaps and internal recovery-domain
|
|
1078
|
-
dependencies. Account labels and provider assignments remain analyst
|
|
1079
|
-
assertions, and the review makes no provider or account request.
|
|
1080
|
-
- `whoisleuth.domain-change.input`: compares bounded, separately labelled
|
|
1081
|
-
authority and resolver observations; reviews CDS, CDNSKEY and CSYNC
|
|
1082
|
-
publication consistency; inventories supplied SRV services and ACME
|
|
1083
|
-
dependencies; and records TLS key continuity, stapling, embedded timestamp,
|
|
1084
|
-
and HSTS preload context. TXT values are retained only as SHA-256 digests.
|
|
1085
|
-
The result is an offline review gate, not a DNSSEC validation, preload-list
|
|
1086
|
-
lookup, certificate-authority request, or permission to apply a change.
|
|
1087
|
-
- `whoisleuth.dns-convergence.input`: compares the latest supplied observation
|
|
1088
|
-
from at least two labelled resolvers or network vantages. It preserves
|
|
1089
|
-
converged, divergent, unexpected, incomplete, and insufficient record-set
|
|
1090
|
-
states, can compare against optional expected values, and projects a simple
|
|
1091
|
-
observation-time plus TTL cache horizon. It does not query DNS or decide
|
|
1092
|
-
which divergent value is authoritative, and supplied TTLs do not reveal
|
|
1093
|
-
actual cache age or resolver refresh policy.
|
|
1094
|
-
- `whoisleuth.nameserver-preflight.input`: reviews an intended nameserver set
|
|
1095
|
-
against separately attributed direct-service observations before a
|
|
1096
|
-
delegation change. It checks authoritative service, the served NS set, SOA
|
|
1097
|
-
evidence, public addresses and in-bailiwick glue readiness without querying
|
|
1098
|
-
DNS, opening a socket or changing registry configuration.
|
|
1099
|
-
- `whoisleuth.trust-store-comparison.input`: compares an already-observed,
|
|
1100
|
-
bounded certificate-chain SHA-256 fingerprint set with up to 16
|
|
1101
|
-
analyst-supplied trust-store snapshots. Each snapshot carries its own name,
|
|
1102
|
-
version, source, review time, completeness, and no more than 2,048 anchor
|
|
1103
|
-
fingerprints. Exact intersections, complete non-observations, and
|
|
1104
|
-
inconclusive inputs remain separate. A match does not build or validate a
|
|
1105
|
-
certificate path, and non-observation does not mean a client would reject
|
|
1106
|
-
the chain because served chains commonly omit their root.
|
|
1107
|
-
|
|
1108
|
-
The common output is `whoisleuth.cli.offline-evidence-review` version 1. It
|
|
1109
|
-
retains the nested result's explicit state and limitations. A locally
|
|
1110
|
-
consistent relationship is not converted into a claim about current
|
|
1111
|
-
publication, ownership, safety, or maliciousness.
|
|
1112
|
-
|
|
1113
|
-
`review-evidence --strict-exit` is an opt-in local automation boundary. It
|
|
1114
|
-
returns the partial-failure exit code when an input family exposes an explicit
|
|
1115
|
-
failed `gate`, or when a zone-intent comparison is incomplete or contains a
|
|
1116
|
-
difference, missing value or unexpected value. Other evidence families retain
|
|
1117
|
-
their ordinary exit behaviour; the flag does not invent a pass/fail policy for
|
|
1118
|
-
them. JSON is still emitted before the exit status is selected.
|
|
1119
|
-
|
|
1120
|
-
## Domain control manifests
|
|
1121
|
-
|
|
1122
|
-
`domain-control [input.json]` builds or reviews a bounded desired-state
|
|
1123
|
-
manifest without making a request or changing configuration. A manifest input
|
|
1124
|
-
uses `whoisleuth.domain-control-manifest-input` version 1, includes an expiry,
|
|
1125
|
-
and may record expected nameservers, DS, MX, CAA, TLS issuer, TLS SPKI
|
|
1126
|
-
fingerprint, registrar-lock preference, and a renewal-review date for up to 100
|
|
1127
|
-
domains. Empty fields mean unconfigured; they do not require a record to be
|
|
1128
|
-
absent.
|
|
1129
|
-
|
|
1130
|
-
The emitted `whoisleuth.domain-control-manifest` version 1 is normalised and
|
|
1131
|
-
protected by a canonical SHA-256 digest. It can also be passed to
|
|
1132
|
-
`sign-artifact` for an optional local Ed25519 signature. Integrity and
|
|
1133
|
-
signature verification detect changes and authenticate possession of the
|
|
1134
|
-
selected key; neither establishes that the desired state is correct. Manifest
|
|
1135
|
-
input and verification reject unknown fields, and verification rejects
|
|
1136
|
-
non-canonical content rather than returning a shape that differs from the
|
|
1137
|
-
normalised contract covered by the digest.
|
|
1138
|
-
|
|
1139
|
-
A review input uses `whoisleuth.domain-control-review-input` version 1 and
|
|
1140
|
-
contains one manifest plus separately attributed observations. Only a complete
|
|
1141
|
-
`observed` field may produce `drift`. Partial, unavailable, unsupported, and
|
|
1142
|
-
missing observations remain inconclusive, and unrelated observations are
|
|
1143
|
-
counted but ignored. The review performs no DNS, RDAP, HTTP, TLS, SMTP, or
|
|
1144
|
-
registrar request.
|
|
1145
|
-
|
|
1146
|
-
## Domain assurance review
|
|
1147
|
-
|
|
1148
|
-
`assurance [input.json]` reviews one bounded analyst-authored workflow entirely
|
|
1149
|
-
offline. Version 1 inputs remain supported. Version 2 adds optional
|
|
1150
|
-
`customChecks` to retirement inputs and remains the current normalised output
|
|
1151
|
-
version. The input uses `whoisleuth.domain-assurance.input` and one of three
|
|
1152
|
-
fixed kinds:
|
|
1153
|
-
|
|
1154
|
-
- `planned-change` records a bounded window, evidence-backed milestones,
|
|
1155
|
-
rollback criteria, and post-change checks;
|
|
1156
|
-
- `recovery-dependencies` reviews up to 100 domains across registrar, DNS,
|
|
1157
|
-
mail, certificate, and recovery providers and highlights exact provider
|
|
1158
|
-
concentration; and
|
|
1159
|
-
- `retirement` checks the fixed decommissioning controls without treating an
|
|
1160
|
-
unchecked item as complete. Version 2 can add up to 20 analyst-defined checks,
|
|
1161
|
-
each with a bounded identifier, label, expected boolean, and true, false, or
|
|
1162
|
-
null observed value.
|
|
1163
|
-
|
|
1164
|
-
Provider labels, readiness confirmations, evidence references, and expected
|
|
1165
|
-
states remain analyst assertions. The output preserves incomplete and
|
|
1166
|
-
needs-review states and gives every negative state an explicit review reason.
|
|
1167
|
-
The versioned input rejects unknown fields and contradictory evidence attached
|
|
1168
|
-
to an unfinished check. It stores no credentials, makes no request, and changes
|
|
1169
|
-
no registrar, DNS, mail, certificate, or recovery configuration.
|
|
1170
|
-
|
|
1171
|
-
## Domain change assurance packet
|
|
1172
|
-
|
|
1173
|
-
`change-packet [input.json]` combines one pre-change domain review, one
|
|
1174
|
-
post-change domain review, and one planned-change assurance input for the same
|
|
1175
|
-
domain. The input uses `whoisleuth.domain-change-packet.input` version 1. The
|
|
1176
|
-
command revalidates each nested contract, summarises changed authoritative
|
|
1177
|
-
record sets, and emits `whoisleuth.domain-change-packet` version 1 with a
|
|
1178
|
-
canonical SHA-256 integrity digest.
|
|
1179
|
-
|
|
1180
|
-
The packet is ready only when both supplied observation reviews and the change
|
|
1181
|
-
plan pass their own bounded gates. Partial or unavailable evidence remains a
|
|
1182
|
-
review reason. Packet assembly performs no collection or configuration change,
|
|
1183
|
-
and digest validity does not authenticate the analyst. A reviewed packet can be
|
|
1184
|
-
passed to `sign-artifact` when the operator has an independently managed
|
|
1185
|
-
Ed25519 signing-key lifecycle.
|
|
1186
|
-
|
|
1187
|
-
## Pre-sharing review
|
|
1188
|
-
|
|
1189
|
-
`sharing-review [artifact.json]` performs a redacted local preflight before an
|
|
1190
|
-
analyst deliberately shares an artefact. The analyst must select a TLP 2.0
|
|
1191
|
-
marking, a recipient scope, and a bounded purpose. Optional confirmations record
|
|
1192
|
-
human review, personal-data review, and redaction review. The command validates
|
|
1193
|
-
supported artefact integrity where possible, detects stricter embedded TLP
|
|
1194
|
-
markings, and reports only key-category counts plus bounded, control-free schema
|
|
1195
|
-
and integer version metadata. It emits no content values and copies no raw
|
|
1196
|
-
evidence.
|
|
1197
|
-
|
|
1198
|
-
An imported stricter marking cannot be downgraded by the requested marking, and
|
|
1199
|
-
recipient scope is checked against the effective marking. Evading this local
|
|
1200
|
-
preflight remains possible, so the result is a review aid rather than access
|
|
1201
|
-
control, legal advice, or recipient authorisation.
|
|
1202
|
-
|
|
1203
|
-
## Fixed investigation plans
|
|
1204
|
-
|
|
1205
|
-
`workflow-plan <recipe> <domain|brand>` turns one of four fixed recipes into a
|
|
1206
|
-
versioned `whoisleuth.cli.investigation-plan` document. Supported recipes are
|
|
1207
|
-
`domain-triage`, `lookalike-review`, `owned-domain-review`, and
|
|
1208
|
-
`historical-comparison`. Each step names an existing CLI command, carries its
|
|
1209
|
-
arguments as a JSON array, declares whether it is offline or networked, and
|
|
1210
|
-
marks network-disclosure or analyst-selection approval gates.
|
|
1211
|
-
|
|
1212
|
-
The command is plan-only. It does not execute a step, construct a shell script,
|
|
1213
|
-
interpret a placeholder as a file path, read an artefact, make a request,
|
|
1214
|
-
change a case, or submit evidence. Analysts deliberately run selected commands
|
|
1215
|
-
after reviewing their collection boundaries. This provides repeatable
|
|
1216
|
-
domain-specific workflows without an arbitrary automation or plugin surface.
|
|
1217
|
-
|
|
1218
|
-
## Local handoffs and one-shot monitoring
|
|
1219
|
-
|
|
1220
|
-
`brief [lookup.json]` reads one saved Lookup and emits version 2 of the bounded
|
|
1221
|
-
`whoisleuth.cli.lookup-brief` contract. It separates retained facts,
|
|
1222
|
-
contradictions, incomplete source states, and manual actions. Each action
|
|
1223
|
-
states its evidence basis and expected outcome; it does not run the action or
|
|
1224
|
-
create a case.
|
|
1225
|
-
|
|
1226
|
-
`case-pack [cases.json] --audience <internal|trusted|public> --reviewed` reads a
|
|
1227
|
-
browser case export containing at most 25 normalised cases, applies the selected
|
|
1228
|
-
redaction boundary, and emits a browser-importable case collection with a
|
|
1229
|
-
canonical SHA-256 digest and redaction manifest. It refuses an invalid,
|
|
1230
|
-
duplicate, larger, or generated package above the browser's 2 MiB import limit
|
|
1231
|
-
rather than silently omitting records or evidence. Trusted output removes notes,
|
|
1232
|
-
recipient values, and manual-pivot targets. Public output additionally removes
|
|
1233
|
-
actions and analyst assertions. The review flag records an explicit choice; it
|
|
1234
|
-
does not prove recipient authorisation or factual correctness.
|
|
1235
|
-
|
|
1236
|
-
`verify-artifact` recognises the complete case-pack envelope before browser
|
|
1237
|
-
import. It checks the canonical digest, supported case-export schema, bounded
|
|
1238
|
-
case count, report count, audience and explicit review marker without printing
|
|
1239
|
-
case contents. This detects a changed hand-off file but does not authenticate
|
|
1240
|
-
the analyst, recipient, source observations, or review decision.
|
|
1241
|
-
|
|
1242
|
-
`monitor-once [manifest.json]` performs one bounded Deep control review for at
|
|
1243
|
-
most 20 manifest domains with concurrency capped at three. An optional
|
|
1244
|
-
`--previous` checkpoint adds local first/last-observed comparison. It is not a
|
|
1245
|
-
daemon or scheduler, retains compact normalised observations rather than raw
|
|
1246
|
-
payloads, and keeps failed collection incomplete. JSON, JUnit, and explicit
|
|
1247
|
-
failure policies are supported.
|
|
1248
|
-
|
|
1249
|
-
`workflow-run <recipe> <subject>` executes only concrete steps from the four
|
|
1250
|
-
installed fixed recipes. Network steps require `--approve-network` for that
|
|
1251
|
-
invocation. Analyst-selection placeholders always pause. A bounded `--resume`
|
|
1252
|
-
state must match the exact recipe and subject, cannot add commands or shell
|
|
1253
|
-
syntax, and is not evidence that earlier results remain current.
|
|
1254
|
-
|
|
1255
|
-
## Optional local rendered capture
|
|
1256
|
-
|
|
1257
|
-
`packages/web-capture` is a private repo-local Playwright package, not part of
|
|
1258
|
-
the distributable core CLI or hosted application. It requires an explicit
|
|
1259
|
-
authorisation flag and one new output directory:
|
|
1260
|
-
|
|
1261
|
-
```bash
|
|
1262
|
-
npm run capture:local -- https://example.test --output-dir ./capture-example --authorize-rendered-capture
|
|
1263
|
-
npm run capture:compare -- ./official/manifest.json ./candidate/manifest.json --json
|
|
1264
|
-
```
|
|
1265
|
-
|
|
1266
|
-
It writes a fixed 1024x768 PNG, screenshot SHA-256 and perceptual dHash, a DOM
|
|
1267
|
-
digest containing hashes and bounded element counts rather than markup or page
|
|
1268
|
-
text, and a version-2 `whoisleuth.web-capture-manifest` compatible with the
|
|
1269
|
-
Cases importer. Version-1 manifests remain importable.
|
|
1270
|
-
|
|
1271
|
-
Rendered capture executes page JavaScript. It caps HTTP(S) requests and request
|
|
1272
|
-
hostnames, blocks downloads, service workers, WebSockets, WebRTC, WebTransport,
|
|
1273
|
-
non-read methods, credentials, non-default ports, and private or reserved
|
|
1274
|
-
addresses, and retains
|
|
1275
|
-
no request path, query, headers, bodies, cookies, credentials, DOM markup, or
|
|
1276
|
-
page text. Every browser request is intercepted, its hostname is resolved again,
|
|
1277
|
-
and the bounded response is fetched through WHOISleuth's public-address-pinned
|
|
1278
|
-
transport. Individual responses are capped at 4 MiB and all fetched response
|
|
1279
|
-
bodies together are capped at 24 MiB. Redirect destinations pass through the
|
|
1280
|
-
same interception and validation before collection continues. Use a disposable
|
|
1281
|
-
network-restricted environment for untrusted targets because rendered page code
|
|
1282
|
-
still executes inside the isolated browser process.
|
|
1283
|
-
|
|
1284
|
-
The separate offline comparison command accepts two selected version-2 local
|
|
1285
|
-
capture manifests. It first verifies each referenced screenshot and DOM digest
|
|
1286
|
-
against its declared size, SHA-256, screenshot dimensions, and perceptual hash;
|
|
1287
|
-
it also validates bounded source and limitation metadata and requires the DOM,
|
|
1288
|
-
manifest, and source collection times to agree. It then
|
|
1289
|
-
compares screenshot distance, exact rendered DOM and visible-text digests,
|
|
1290
|
-
bounded element counts, page identity, technologies, and request-domain sets.
|
|
1291
|
-
It does not recrawl either target, reveal the input paths, or collapse the
|
|
1292
|
-
independent components into a similarity or maliciousness score. A missing
|
|
1293
|
-
perceptual hash remains unavailable rather than becoming a visual difference.
|
|
1294
|
-
|
|
1295
|
-
## Lookup evidence export
|
|
1296
|
-
|
|
1297
|
-
`export` converts one version-1 `whoisleuth.cli.lookup` domain document from a
|
|
1298
|
-
file or stdin into the same versioned `whoisleuth.lookup-evidence` JSON package
|
|
1299
|
-
produced by the web Lookup tool. It performs no lookup and writes only to
|
|
1300
|
-
stdout, so use ordinary shell redirection when a file is wanted. Pretty JSON is
|
|
1301
|
-
the default; `--compact` emits one compact JSON line for pipeline use, while
|
|
1302
|
-
`--markdown` produces a readable source-attributed summary and `--html`
|
|
1303
|
-
produces a self-contained printable report. Compact, Markdown, and HTML output
|
|
1304
|
-
are mutually exclusive.
|
|
1305
|
-
|
|
1306
|
-
The saved input is capped at 8 MiB and revalidated using the same schema,
|
|
1307
|
-
source-status, parsed-data, scalar, list, and event boundaries as `compare`.
|
|
1308
|
-
The export retains query context, source diagnostics, normalised registry data,
|
|
1309
|
-
raw registry RDAP JSON, the raw WHOIS referral chain, availability analysis,
|
|
1310
|
-
and the shared registry-source comparison. Version 23 can add the exact local
|
|
1311
|
-
SSLBL comparison already represented by a deep full Lookup. Version 21 adds the bounded registry
|
|
1312
|
-
lifecycle, disclosure, publication-quality, reconciliation, and abuse-routing
|
|
1313
|
-
interpretation derived from the already-collected sources. Registrar RDAP raw
|
|
1314
|
-
data, contacts, entities, links, notices, and source-specific handles remain
|
|
1315
|
-
excluded. Schema version 20 replaces selected security-policy values in
|
|
1316
|
-
retained HTTP evidence
|
|
1317
|
-
with presence-only markers and can include fixed response-policy findings from
|
|
1318
|
-
an already-represented deep lookup. Version 19 additionally retains the bounded credential-surface projection
|
|
1319
|
-
when the saved deep lookup represents it. Version 18 retains the bounded structured identity projection
|
|
1320
|
-
when the saved deep lookup represents it. Version 17 retains the normalised portable-field comparison, explicit
|
|
1321
|
-
source-health states, a strict bounded projection of observed network
|
|
1322
|
-
registration, an optional normalised security.txt disclosure source, HTTPS
|
|
1323
|
-
service-binding publications, and the passive browser-library profile when the
|
|
1324
|
-
saved deep lookup represents them. Raw IP RDAP payloads, security.txt response
|
|
1325
|
-
bodies, script references, matched script content, and contact entities remain
|
|
1326
|
-
excluded.
|
|
1327
|
-
|
|
1328
|
-
Markdown output summarises query context, assessment state, registry sources,
|
|
1329
|
-
source reconciliation, network observations, and collection diagnostics. It
|
|
1330
|
-
escapes all upstream text as untrusted content, bounds displayed values and
|
|
1331
|
-
lists, and deliberately omits raw RDAP JSON and full WHOIS response bodies.
|
|
1332
|
-
Use JSON when the complete evidence package or machine processing is required.
|
|
1333
|
-
The browser Console reuses this bounded Markdown renderer for domain results
|
|
1334
|
-
after first reducing the typed Lookup response to the known normalised fields
|
|
1335
|
-
needed by the report. It separately offers bounded IP and ASN summaries from
|
|
1336
|
-
their normalised RDAP and source-health fields; IP reports can also include
|
|
1337
|
-
bounded reverse-DNS context already collected by Lookup. The browser action
|
|
1338
|
-
does not change the CLI input or output contract.
|
|
1339
|
-
When a version-5, version-6, or version-7 lookup records a documented registry-access constraint, both
|
|
1340
|
-
Markdown and HTML include that context in collection diagnostics without
|
|
1341
|
-
changing its non-authoritative interpretation. Both formats also include the
|
|
1342
|
-
selected address and bounded network registration when present, together with
|
|
1343
|
-
the edge-versus-origin limitation.
|
|
1344
|
-
|
|
1345
|
-
HTML uses the same bounded summary model as Markdown. The generated document
|
|
1346
|
-
contains inline styling for screen and print, but no scripts, forms, active
|
|
1347
|
-
links, or external resources. A restrictive embedded Content Security Policy
|
|
1348
|
-
provides defence in depth when the local file is opened in a browser. All
|
|
1349
|
-
registry values are HTML-escaped and displayed as text.
|
|
1350
|
-
|
|
1351
|
-
This is a deliberately rich evidence package. Raw registry sources can contain
|
|
1352
|
-
publicly published contact data, and deep availability evidence can contain
|
|
1353
|
-
bounded website, DNS, mail, page-identity, and TLS observations. Review and
|
|
1354
|
-
secure the output before sharing it. The CLI does not add browser-only IDN
|
|
1355
|
-
profile analysis, so that optional evidence field is `null`.
|
|
96
|
+
| 0 | The command completed; individual sources can still be partial. |
|
|
97
|
+
| 2 | The command, option or input was invalid. |
|
|
98
|
+
| 3 | Collection, lookup or comparison failed. |
|
|
99
|
+
| 4 | The result was partial or a selected evidence policy was not met. |
|
|
100
|
+
| 70 | The CLI could not complete bootstrap. |
|
|
101
|
+
| 130 | The analyst cancelled; no partial final result was emitted. |
|
|
102
|
+
| 143 | SIGTERM stopped the process; no partial final result was emitted. |
|
|
103
|
+
|
|
104
|
+
## Portable documents and compatibility
|
|
105
|
+
|
|
106
|
+
Readers accept only their declared public and current versions. Unknown,
|
|
107
|
+
unreleased historical and future schemas fail before partial interpretation;
|
|
108
|
+
an invalid import is not treated as an empty document.
|
|
109
|
+
|
|
110
|
+
`inspect-archive` reads current workspace archive v6 and exact public v5. It
|
|
111
|
+
reports section metadata and digest-only search results unless `--reveal` is
|
|
112
|
+
explicitly selected. It never searches notes, contacts or arbitrary raw fields.
|
|
113
|
+
|
|
114
|
+
`export` reads supported saved Lookup v1 or v2 and writes current Lookup
|
|
115
|
+
evidence schema 27. Exact public schema 26 remains readable and can contain
|
|
116
|
+
public contact fields; current schema 27 excludes raw registration payloads,
|
|
117
|
+
expanded contacts, credentials, complete query-bearing URLs and provider
|
|
118
|
+
payloads.
|
|
119
|
+
|
|
120
|
+
`verify-artifact` checks a recognised structure and its applicable integrity
|
|
121
|
+
contract. `interchange-report` describes retained and omitted fields.
|
|
122
|
+
`sign-artifact` and `verify-signature` keep artefact validity, signature
|
|
123
|
+
validity and signer trust separate. None of these checks establishes that
|
|
124
|
+
evidence is accurate, current, safe to share or attributable to a person.
|
|
125
|
+
|
|
126
|
+
## Command-family boundaries
|
|
127
|
+
|
|
128
|
+
- Evidence collection commands retain separate source states. A failed or
|
|
129
|
+
missing supporting source is not converted into absence, availability or a
|
|
130
|
+
favourable score.
|
|
131
|
+
- Discover and Certificate Transparency commands produce review candidates.
|
|
132
|
+
Generation, publication and shared infrastructure do not establish ownership,
|
|
133
|
+
control, activity, intent or maliciousness.
|
|
134
|
+
- Bulk applies one declared collection contract per target. Fast accepts up to
|
|
135
|
+
500 targets and Deep up to 50; each target remains a separate request.
|
|
136
|
+
- Respond commands prepare local Cases, packets and sharing reviews. They do not
|
|
137
|
+
submit, publish, notify or grant recipient authorisation.
|
|
138
|
+
- Assurance, comparison and calibration commands describe supplied or retained
|
|
139
|
+
evidence. They do not tune the running model, change infrastructure or turn an
|
|
140
|
+
analyst label into observed truth.
|
|
141
|
+
- `workflow-plan` lists fixed installed recipes without executing them.
|
|
142
|
+
`workflow-run` executes only installed steps, requires approval for network
|
|
143
|
+
work and pauses for analyst-selection placeholders.
|
|
144
|
+
|
|
145
|
+
Use the installed focused help for positional inputs, exact ceilings, options,
|
|
146
|
+
network effects, outputs and command-specific exit behaviour.
|