@slicedearth/whoisleuth-cli 1.39.1 → 1.45.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/README.md +23 -4
- package/bin/whoisleuth.mjs +31 -9
- package/cli/archive-inspect.mjs +37 -2
- package/cli/arguments.mjs +361 -256
- package/cli/artifact-verify.mjs +35 -1
- package/cli/bulk-checkpoint.mjs +72 -39
- package/cli/bulk-command-runner.mjs +34 -4
- package/cli/bulk.mjs +18 -7
- package/cli/case-pack.mjs +136 -0
- package/cli/ci-report.mjs +73 -0
- package/cli/collection-preflight.mjs +59 -0
- package/cli/command-reference.mjs +395 -0
- package/cli/completion.mjs +67 -13
- package/cli/config-profile.mjs +183 -0
- package/cli/ct-event-intake.mjs +159 -0
- package/cli/discovery-observation-snapshot.mjs +8 -14
- package/cli/discovery-scan-command-runner.mjs +29 -2
- package/cli/discovery-snapshot.mjs +8 -15
- package/cli/domain-control-monitor.mjs +104 -0
- package/cli/domain-control-observations.mjs +235 -0
- package/cli/errors.mjs +7 -1
- package/cli/evidence-command-arguments.mjs +11 -0
- package/cli/evidence-command-runner.mjs +1 -0
- package/cli/external-observation-mapping.mjs +162 -0
- package/cli/fail-policy.mjs +64 -0
- package/cli/formatters/html.mjs +1 -1
- package/cli/formatters/json.mjs +12 -4
- package/cli/formatters/terminal.mjs +1 -1
- package/cli/http.mjs +2 -1
- package/cli/investigation-manifest.mjs +113 -0
- package/cli/investigation-run.mjs +112 -0
- package/cli/lookup-brief.mjs +116 -0
- package/cli/lookup-command-runner.mjs +8 -1
- package/cli/lookup-diff.mjs +17 -19
- package/cli/lookup-reconcile.mjs +1 -1
- package/cli/mail-review.mjs +5 -5
- package/cli/manual.mjs +1 -1
- package/cli/network-command-runner.mjs +4 -1
- package/cli/offline-evidence-review.mjs +105 -8
- package/cli/open-asset-model-bridge.mjs +169 -0
- package/cli/registry-cohort.mjs +121 -0
- package/cli/registry-doctor.mjs +106 -11
- package/cli/registry-fixture-scaffold.mjs +74 -0
- package/cli/runner.mjs +388 -315
- package/docs/cli-reference.md +266 -21
- package/docs/cli.md +43 -7
- package/frontend/src/lib/analysis/acquisition-due-diligence.js +2 -2
- package/frontend/src/lib/analysis/brand-profile-model.js +50 -6
- package/frontend/src/lib/analysis/case-evidence-model.js +1 -1
- package/frontend/src/lib/analysis/case-record-core.js +1 -1
- package/frontend/src/lib/analysis/case-record-operations.js +1 -1
- package/frontend/src/lib/analysis/case-report.js +573 -0
- package/frontend/src/lib/analysis/case-response-model.js +30 -1
- package/frontend/src/lib/analysis/detection-rule-model.js +36 -0
- package/frontend/src/lib/analysis/external-findings-import.js +320 -0
- package/frontend/src/lib/analysis/lookup-asset-graph.js +8 -8
- package/frontend/src/lib/analysis/lookup-decision-support.js +9 -2
- package/frontend/src/lib/analysis/lookup-presentation.js +14 -30
- package/frontend/src/lib/analysis/lookup-source-refresh.js +36 -63
- package/frontend/src/lib/analysis/scoring.js +1 -1
- package/frontend/src/lib/analysis/utils.js +1 -1
- package/frontend/src/lib/analysis/visualization-models.js +2 -3
- package/frontend/src/lib/analysis/workspace-archive-crypto.js +1 -4
- package/frontend/src/lib/analysis/workspace-archive.js +5 -7
- package/lib/abusech-auth.mjs +1 -1
- package/lib/availability.mjs +1 -1
- package/lib/bounded-contract-normalizers.mjs +33 -0
- package/lib/bounded-file.mjs +69 -0
- package/lib/bounded-json-response.mjs +157 -0
- package/lib/browser-library-profile.mjs +167 -38
- package/lib/dns-convergence-review.mjs +183 -0
- package/lib/dns-delegation-health.mjs +196 -3
- package/lib/domain-change-packet.mjs +133 -0
- package/lib/domain-change-review.mjs +307 -0
- package/lib/domain-control-flight-recorder.mjs +268 -0
- package/lib/domain-portfolio-review.mjs +151 -0
- package/lib/evidence-export.mjs +1 -1
- package/lib/html-signals.mjs +5 -11
- package/lib/lookup-cache.mjs +5 -1
- package/lib/nameserver-preflight-review.mjs +159 -0
- package/lib/page-language-signals.mjs +124 -0
- package/lib/rdap-transport.mjs +6 -6
- package/lib/risk-scoring.mjs +42 -1
- package/lib/safe-fetch.mjs +37 -32
- package/lib/static-html-analysis.mjs +29 -1
- package/lib/threat-intelligence-runtime.mjs +1 -2
- package/lib/trust-store-comparison.mjs +146 -0
- package/lib/website-technology.mjs +22 -12
- package/lib/zone-intent-review.mjs +534 -0
- package/package.json +1 -1
package/docs/cli-reference.md
CHANGED
|
@@ -69,6 +69,8 @@ node bin/whoisleuth.mts http example.com --json
|
|
|
69
69
|
node bin/whoisleuth.mts tls example.com --json
|
|
70
70
|
node bin/whoisleuth.mts registry-support example.uk --json
|
|
71
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
|
|
72
74
|
node bin/whoisleuth.mts risk-calibrate calibration.json --json
|
|
73
75
|
node bin/whoisleuth.mts lookalike-calibrate reviewed-candidates.json --json
|
|
74
76
|
node bin/whoisleuth.mts verify-artifact workspace.json --json
|
|
@@ -78,16 +80,26 @@ node bin/whoisleuth.mts source-report lookup.json --json
|
|
|
78
80
|
node bin/whoisleuth.mts inspect-archive workspace.json --json
|
|
79
81
|
node bin/whoisleuth.mts inspect-archive workspace.json --search example.invalid --json
|
|
80
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
|
|
81
87
|
node bin/whoisleuth.mts verify-signature response-packet.signed.json --public-key-file analyst-public.pem
|
|
82
88
|
node bin/whoisleuth.mts lookup example.com --deep --json > lookup.json
|
|
83
89
|
node bin/whoisleuth.mts compare lookup.json --json
|
|
84
90
|
node bin/whoisleuth.mts page-compare official.json candidate.json --json
|
|
85
91
|
node bin/whoisleuth.mts mail-review bulk.json --json
|
|
86
92
|
node bin/whoisleuth.mts review-evidence dnssec-evidence.json --json
|
|
93
|
+
node bin/whoisleuth.mts review-evidence trust-store-comparison.json --json
|
|
87
94
|
node bin/whoisleuth.mts domain-control domain-control-input.json --json
|
|
88
95
|
node bin/whoisleuth.mts assurance domain-assurance-input.json --json
|
|
96
|
+
node bin/whoisleuth.mts change-packet domain-change-packet-input.json --json
|
|
89
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
|
|
90
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
|
|
91
103
|
node bin/whoisleuth.mts diff first-lookup.json second-lookup.json --json
|
|
92
104
|
node bin/whoisleuth.mts reconcile office.json mobile.json external.json --json
|
|
93
105
|
node bin/whoisleuth.mts timeline first-observation.json second-observation.json latest-observation.json --json
|
|
@@ -193,9 +205,11 @@ Commands that query RDAP, WHOIS, DNS, HTTP, TLS, or Certificate Transparency do
|
|
|
193
205
|
so directly from the machine running the CLI. They do not use the hosted login,
|
|
194
206
|
hosted session, or deployment usage controls; upstream providers can see and
|
|
195
207
|
rate-limit the local machine's network address. Offline `discover`, `compare`,
|
|
196
|
-
`page-compare`, `mail-review`, `review-evidence`, `domain-control`, `assurance`,
|
|
197
|
-
`sharing-review`, `workflow-plan`, `
|
|
198
|
-
`
|
|
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`,
|
|
199
213
|
`commands`, `completion`, and `manual` operations make no network requests. Commands write
|
|
200
214
|
to stdout unless the analyst deliberately selects a local output file.
|
|
201
215
|
|
|
@@ -218,6 +232,23 @@ An existing destination is refused. `--force` is valid only with `--output` and
|
|
|
218
232
|
allows an intentional atomic replacement. A failed or cancelled command does
|
|
219
233
|
not publish a partial output file. Output is capped at 32 MiB.
|
|
220
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
|
+
|
|
221
252
|
`lookup --markdown` and `lookup --html` build the existing normalised evidence
|
|
222
253
|
report directly after one completed domain lookup. They do not start a second
|
|
223
254
|
collection. These report formats reject IP and ASN inputs before collection;
|
|
@@ -299,7 +330,8 @@ delivery observed by the caller.
|
|
|
299
330
|
|
|
300
331
|
Pressing Ctrl-C asks an in-flight Lookup or Bulk run to stop, suppresses any
|
|
301
332
|
partial final result, flushes an enabled Bulk checkpoint, and exits with code
|
|
302
|
-
130.
|
|
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
|
|
303
335
|
timeouts while the shared in-process API unwinds; the executable terminates
|
|
304
336
|
after CLI cleanup. A second Ctrl-C removes any known unpublished temporary
|
|
305
337
|
output file on a best-effort basis before exiting immediately.
|
|
@@ -307,11 +339,23 @@ output file on a best-effort basis before exiting immediately.
|
|
|
307
339
|
Bulk can persist compact progress with `--checkpoint <file>`. A new checkpoint
|
|
308
340
|
is private, bounded to 16 MiB, versioned, and tied to the exact ordered input
|
|
309
341
|
and scan mode by SHA-256. It stores only compact per-item results, never full
|
|
310
|
-
Lookup responses.
|
|
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
|
|
311
346
|
specified. Resume revalidates the complete untrusted document and skips only
|
|
312
347
|
the exact completed rows; changed input, mode, schema, digest, or malformed
|
|
313
348
|
results fail closed.
|
|
314
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
|
+
|
|
315
359
|
If checkpoint persistence fails after collection, WHOISleuth still emits the
|
|
316
360
|
completed final result, reports the checkpoint limitation, and exits with code
|
|
317
361
|
4. The last successfully published checkpoint remains available, but it may
|
|
@@ -362,13 +406,14 @@ machine access is not evidence that a domain is unregistered or safe.
|
|
|
362
406
|
| 4 | A bounded operation completed partially, such as Bulk item failures or failed explicit Doctor network checks. |
|
|
363
407
|
| 70 | Unexpected CLI bootstrap failure. |
|
|
364
408
|
| 130 | The analyst cancelled the command. No partial final result was emitted. |
|
|
409
|
+
| 143 | The process received SIGTERM. No partial final result was emitted. |
|
|
365
410
|
|
|
366
|
-
This release supports `lookup`, `bulk`, `ct-search`, `discover`, `discover-scan`, `posture`,
|
|
367
|
-
`http`, `tls`, `registry-support`, `registry-doctor`, `risk-calibrate`,
|
|
411
|
+
This release supports `lookup`, `bulk`, `ct-search`, `ct-intake`, `map-observations`, `oam-export`, `discover`, `discover-scan`, `posture`,
|
|
412
|
+
`http`, `tls`, `registry-support`, `registry-doctor`, `registry-cohort`, `registry-scaffold`, `risk-calibrate`,
|
|
368
413
|
`lookalike-calibrate`, `verify-artifact`,
|
|
369
|
-
`inspect-archive`, `sign-artifact`, `verify-signature`, `source-report`,
|
|
370
|
-
`compare`, `page-compare`, `mail-review`, `review-evidence`, `domain-control`,
|
|
371
|
-
`assurance`, `sharing-review`, `workflow-plan`, `diff`, `reconcile`, `timeline`,
|
|
414
|
+
`inspect-archive`, `manifest`, `sign-artifact`, `verify-signature`, `source-report`,
|
|
415
|
+
`compare`, `page-compare`, `mail-review`, `review-evidence`, `brief`, `case-pack`, `domain-control`,
|
|
416
|
+
`monitor-once`, `assurance`, `change-packet`, `sharing-review`, `workflow-plan`, `workflow-run`, `diff`, `reconcile`, `timeline`,
|
|
372
417
|
`export`, `doctor`, `commands`, `completion`, and `manual`. Additional command families
|
|
373
418
|
are added as separate bounded increments rather than exposing incomplete
|
|
374
419
|
aliases.
|
|
@@ -395,10 +440,24 @@ ownership, safety, or maliciousness.
|
|
|
395
440
|
`registry-doctor [lookup.json]` compares one saved domain Lookup with the same
|
|
396
441
|
reviewed local capability profile. It reports whether RDAP and WHOIS collection
|
|
397
442
|
states align with allowed, permission-required, or unsupported access, counts
|
|
398
|
-
bounded normalised publication fields, and reports
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
443
|
+
bounded normalised publication fields, and reports publication-quality context
|
|
444
|
+
for object identity, base conformance, redaction metadata, required self links,
|
|
445
|
+
and event consistency. A missing identifier or metadata field is a publication
|
|
446
|
+
omission, not a failed lookup. The command is offline, makes no retry, and
|
|
447
|
+
cannot establish current registry reachability.
|
|
448
|
+
|
|
449
|
+
`registry-cohort [lookups.json|lookups.jsonl]` aggregates from 1 to 500 saved
|
|
450
|
+
Lookups into suffix and capability-profile cohorts. It retains only target-free
|
|
451
|
+
counts for source alignment and publication-quality states. A cohort with
|
|
452
|
+
fewer than five samples is labelled insufficient rather than treated as a
|
|
453
|
+
quality result, and repeated observations from one environment are not assumed
|
|
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.
|
|
402
461
|
|
|
403
462
|
The offline RDAP supplied-evidence review implements the request shape defined
|
|
404
463
|
by RFC 9536 for `resources`, `domains`, `nameservers`, and `entities`. It also
|
|
@@ -513,7 +572,9 @@ establish that a current candidate is malicious or safe.
|
|
|
513
572
|
evidence contents. Input is capped at 15 MiB. It currently recognises ordinary
|
|
514
573
|
and encrypted workspace archives, case-response packets, acquisition-decision
|
|
515
574
|
exports, domain-comparison exports, Bulk mail-exposure exports, and Bulk review
|
|
516
|
-
manifests.
|
|
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
|
|
517
578
|
capsule, including its evidence, brief, graph, and optional analyst-record
|
|
518
579
|
projections, and that capsule can be passed to `sign-artifact`. It also validates the bounded versioned structure of saved CLI
|
|
519
580
|
Lookup JSON. Because saved Lookup documents do not embed a checksum or
|
|
@@ -573,6 +634,17 @@ DNS-safe ASCII form before exact comparison. `--require-match` makes a
|
|
|
573
634
|
no-match result fail for automation and is valid only with `--search`.
|
|
574
635
|
Traversal, input size, matches, depth, arrays, and strings are bounded.
|
|
575
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
|
+
|
|
576
648
|
## Optional evidence-package signing
|
|
577
649
|
|
|
578
650
|
`sign-artifact` signs a locally verified case-response packet or supported
|
|
@@ -592,6 +664,23 @@ verification establishes only that the package is internally self-consistent.
|
|
|
592
664
|
WHOISleuth does not generate, store, recover, rotate, publish, or establish
|
|
593
665
|
trust in signing keys.
|
|
594
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
|
+
|
|
595
684
|
## Bulk lookup
|
|
596
685
|
|
|
597
686
|
`bulk` accepts a newline-delimited file or stdin. It preserves input order,
|
|
@@ -642,6 +731,56 @@ the complete bounded structured result in the versioned
|
|
|
642
731
|
separately from the registrable-domain result cap. CT observations do not prove
|
|
643
732
|
that a website is active or malicious.
|
|
644
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
|
+
|
|
645
784
|
## Lookalike discovery
|
|
646
785
|
|
|
647
786
|
`discover` runs the same pure, bounded lookalike generator as the Discover
|
|
@@ -907,7 +1046,10 @@ Supported input schemas are:
|
|
|
907
1046
|
The command does not retrieve the certificate or negotiate STARTTLS.
|
|
908
1047
|
- `whoisleuth.rdap-search-input`: normalises a supplied RDAP search-help
|
|
909
1048
|
response and prepares an exact supported reverse-search request without
|
|
910
|
-
sending it.
|
|
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.
|
|
911
1053
|
- `whoisleuth.rpki-route-input`: compares a route prefix and origin ASN with a
|
|
912
1054
|
bounded analyst-supplied VRP set.
|
|
913
1055
|
- `whoisleuth.local-geoip-query`: queries an analyst-supplied bounded prefix
|
|
@@ -924,12 +1066,57 @@ Supported input schemas are:
|
|
|
924
1066
|
- `whoisleuth.encrypted-dns-plan-input`: validates an explicitly reviewed
|
|
925
1067
|
encrypted-DNS provider contract and prepares a bounded query plan. It does
|
|
926
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.
|
|
927
1107
|
|
|
928
1108
|
The common output is `whoisleuth.cli.offline-evidence-review` version 1. It
|
|
929
1109
|
retains the nested result's explicit state and limitations. A locally
|
|
930
1110
|
consistent relationship is not converted into a claim about current
|
|
931
1111
|
publication, ownership, safety, or maliciousness.
|
|
932
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
|
+
|
|
933
1120
|
## Domain control manifests
|
|
934
1121
|
|
|
935
1122
|
`domain-control [input.json]` builds or reviews a bounded desired-state
|
|
@@ -981,6 +1168,22 @@ The versioned input rejects unknown fields and contradictory evidence attached
|
|
|
981
1168
|
to an unfinished check. It stores no credentials, makes no request, and changes
|
|
982
1169
|
no registrar, DNS, mail, certificate, or recovery configuration.
|
|
983
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
|
+
|
|
984
1187
|
## Pre-sharing review
|
|
985
1188
|
|
|
986
1189
|
`sharing-review [artifact.json]` performs a redacted local preflight before an
|
|
@@ -1012,6 +1215,43 @@ change a case, or submit evidence. Analysts deliberately run selected commands
|
|
|
1012
1215
|
after reviewing their collection boundaries. This provides repeatable
|
|
1013
1216
|
domain-specific workflows without an arbitrary automation or plugin surface.
|
|
1014
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
|
+
|
|
1015
1255
|
## Optional local rendered capture
|
|
1016
1256
|
|
|
1017
1257
|
`packages/web-capture` is a private repo-local Playwright package, not part of
|
|
@@ -1029,12 +1269,17 @@ text, and a version-2 `whoisleuth.web-capture-manifest` compatible with the
|
|
|
1029
1269
|
Cases importer. Version-1 manifests remain importable.
|
|
1030
1270
|
|
|
1031
1271
|
Rendered capture executes page JavaScript. It caps HTTP(S) requests and request
|
|
1032
|
-
hostnames, blocks downloads, service workers, WebSockets,
|
|
1033
|
-
credentials, non-default ports, and private or reserved
|
|
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
|
|
1034
1275
|
no request path, query, headers, bodies, cookies, credentials, DOM markup, or
|
|
1035
|
-
page text.
|
|
1036
|
-
|
|
1037
|
-
|
|
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.
|
|
1038
1283
|
|
|
1039
1284
|
The separate offline comparison command accepts two selected version-2 local
|
|
1040
1285
|
capture manifests. It first verifies each referenced screenshot and DOM digest
|
package/docs/cli.md
CHANGED
|
@@ -67,6 +67,8 @@ whoisleuth bulk domains.txt --csv
|
|
|
67
67
|
whoisleuth discover example.com --preset common --jsonl
|
|
68
68
|
whoisleuth verify-artifact lookup.json --json
|
|
69
69
|
whoisleuth compare lookup.json --json
|
|
70
|
+
whoisleuth brief lookup.json
|
|
71
|
+
whoisleuth registry-doctor lookup.json --json
|
|
70
72
|
```
|
|
71
73
|
|
|
72
74
|
Only one query is accepted by `lookup`; multi-input processing belongs to
|
|
@@ -105,13 +107,13 @@ HTTP status, and a bounded explanation.
|
|
|
105
107
|
| Goal | Commands |
|
|
106
108
|
| --- | --- |
|
|
107
109
|
| Investigate a target | `lookup`, `http`, `tls`, `posture`, `registry-support` |
|
|
108
|
-
| Review many targets | `bulk`, `discover`, `discover-scan`, `ct-search` |
|
|
110
|
+
| Review many targets | `bulk`, `discover`, `discover-scan`, `ct-search`, `ct-intake` |
|
|
109
111
|
| Compare saved evidence | `compare`, `page-compare`, `diff`, `reconcile`, `timeline`, `mail-review` |
|
|
110
|
-
| Review supplied evidence | `review-evidence`, `registry-doctor`, `source-report`, `sharing-review` |
|
|
111
|
-
| Plan and assure changes | `domain-control`, `assurance`, `workflow-plan` |
|
|
112
|
-
| Verify and package evidence | `verify-artifact`, `inspect-archive`, `sign-artifact`, `verify-signature`, `export` |
|
|
112
|
+
| Review supplied evidence | `brief`, `review-evidence`, `registry-doctor`, `registry-cohort`, `source-report`, `sharing-review`, `map-observations` |
|
|
113
|
+
| Plan and assure changes | `domain-control`, `monitor-once`, `assurance`, `change-packet`, `workflow-plan`, `workflow-run` |
|
|
114
|
+
| Verify and package evidence | `case-pack`, `manifest`, `oam-export`, `verify-artifact`, `inspect-archive`, `sign-artifact`, `verify-signature`, `export` |
|
|
113
115
|
| Calibrate offline | `risk-calibrate`, `lookalike-calibrate` |
|
|
114
|
-
| Operate the CLI | `doctor`, `commands`, `completion`, `manual` |
|
|
116
|
+
| Operate the CLI | `doctor`, `registry-scaffold`, `commands`, `completion`, `manual` |
|
|
115
117
|
|
|
116
118
|
Use focused help for the exact arguments and collection ceiling:
|
|
117
119
|
|
|
@@ -137,6 +139,18 @@ explicit in text, so colour is never the only distinction.
|
|
|
137
139
|
lifecycle events to stderr.
|
|
138
140
|
- `--strict-exit` treats failures in explicitly requested source families as a
|
|
139
141
|
partial failure while keeping skipped or unsupported sources neutral.
|
|
142
|
+
- `--fail-on` applies explicit `source-failure`, `inconclusive`, `danger`, or
|
|
143
|
+
`material-drift` automation policy where the selected command supports it.
|
|
144
|
+
- `--junit` emits bounded CI test cases for Lookup, Bulk, and one-shot control
|
|
145
|
+
reviews; owned-domain Posture can emit `--sarif` only with
|
|
146
|
+
`--owned-domain`.
|
|
147
|
+
|
|
148
|
+
`--config <file> --profile <name>` applies a strict version-1 local profile.
|
|
149
|
+
The default path is `$XDG_CONFIG_HOME/whoisleuth/config.json`. Profiles can set
|
|
150
|
+
only presentation mode, Fast collection, bounded concurrency, and observer or
|
|
151
|
+
vantage labels. They cannot add targets, enable Deep collection, select output
|
|
152
|
+
paths, approve network work, or set failure policy. Explicit command options
|
|
153
|
+
override defaults from the same option group.
|
|
140
154
|
|
|
141
155
|
Every command accepts `--output <file>`. WHOISleuth buffers bounded output,
|
|
142
156
|
creates a private temporary file beside the destination, syncs it, and publishes
|
|
@@ -154,6 +168,7 @@ commands do not publish partial files. Output is capped at 32 MiB.
|
|
|
154
168
|
| 4 | A bounded operation completed partially. |
|
|
155
169
|
| 70 | Unexpected CLI bootstrap failure. |
|
|
156
170
|
| 130 | The analyst cancelled the command; no partial final result was emitted. |
|
|
171
|
+
| 143 | The process received SIGTERM; no partial final result was emitted. |
|
|
157
172
|
|
|
158
173
|
## Detailed command reference
|
|
159
174
|
|
|
@@ -182,12 +197,17 @@ full contracts into the packaged reference.
|
|
|
182
197
|
|
|
183
198
|
### Workspace archive inspection
|
|
184
199
|
|
|
185
|
-
[Read the redacted archive summary
|
|
200
|
+
[Read the redacted archive summary, stable content-digest, transfer-check, and
|
|
201
|
+
search contract.](cli-reference.md#workspace-archive-inspection)
|
|
186
202
|
|
|
187
203
|
### Optional evidence-package signing
|
|
188
204
|
|
|
189
205
|
[Read the local signing and verification contract.](cli-reference.md#optional-evidence-package-signing)
|
|
190
206
|
|
|
207
|
+
### Reproducible investigation manifest
|
|
208
|
+
|
|
209
|
+
[Read the ordered, path-free artefact digest contract.](cli-reference.md#reproducible-investigation-manifest)
|
|
210
|
+
|
|
191
211
|
### Bulk lookup
|
|
192
212
|
|
|
193
213
|
[Read Bulk bounds, filters, formats, checkpoints, and cancellation behaviour.](cli-reference.md#bulk-lookup)
|
|
@@ -196,6 +216,14 @@ full contracts into the packaged reference.
|
|
|
196
216
|
|
|
197
217
|
[Read the CT query and source-limit contract.](cli-reference.md#certificate-transparency-search)
|
|
198
218
|
|
|
219
|
+
### Local certificate event intake
|
|
220
|
+
|
|
221
|
+
[Read the offline, source-qualified event import contract.](cli-reference.md#local-certificate-event-intake)
|
|
222
|
+
|
|
223
|
+
### Declarative observation interchange
|
|
224
|
+
|
|
225
|
+
[Read the bounded field-mapping and Open Asset Model bridge contracts.](cli-reference.md#declarative-observation-interchange)
|
|
226
|
+
|
|
199
227
|
### Lookalike discovery
|
|
200
228
|
|
|
201
229
|
[Read candidate generation, dictionaries, snapshots, and output behaviour.](cli-reference.md#lookalike-discovery)
|
|
@@ -230,7 +258,7 @@ full contracts into the packaged reference.
|
|
|
230
258
|
|
|
231
259
|
### Offline supplied-evidence review
|
|
232
260
|
|
|
233
|
-
[Read the DNSSEC, DANE, and supplied-observation review contract.](cli-reference.md#offline-supplied-evidence-review)
|
|
261
|
+
[Read the DNSSEC, DANE, zone-intent, portfolio, domain-change, and supplied-observation review contract.](cli-reference.md#offline-supplied-evidence-review)
|
|
234
262
|
|
|
235
263
|
### Domain control manifests
|
|
236
264
|
|
|
@@ -240,6 +268,10 @@ full contracts into the packaged reference.
|
|
|
240
268
|
|
|
241
269
|
[Read planned-change, recovery-dependency, and retirement contracts.](cli-reference.md#domain-assurance-review)
|
|
242
270
|
|
|
271
|
+
### Domain change assurance packet
|
|
272
|
+
|
|
273
|
+
[Read the bounded pre-change, post-change, planning, and integrity contract.](cli-reference.md#domain-change-assurance-packet)
|
|
274
|
+
|
|
243
275
|
### Pre-sharing review
|
|
244
276
|
|
|
245
277
|
[Read the local marking, scope, redaction, and integrity preflight.](cli-reference.md#pre-sharing-review)
|
|
@@ -248,6 +280,10 @@ full contracts into the packaged reference.
|
|
|
248
280
|
|
|
249
281
|
[Read the plan-only recipe contract and approval gates.](cli-reference.md#fixed-investigation-plans)
|
|
250
282
|
|
|
283
|
+
### Local handoffs and one-shot monitoring
|
|
284
|
+
|
|
285
|
+
[Read brief, case-package, fixed-recipe execution, and one-shot control-review contracts.](cli-reference.md#local-handoffs-and-one-shot-monitoring)
|
|
286
|
+
|
|
251
287
|
### Optional local rendered capture
|
|
252
288
|
|
|
253
289
|
[Read the separate Playwright capture package boundary.](cli-reference.md#optional-local-rendered-capture)
|
|
@@ -205,7 +205,7 @@ function contactsItem(insights) {
|
|
|
205
205
|
function sourceComplete(evidence) {
|
|
206
206
|
return evidence.source === 'dns' && evidence.complete === true;
|
|
207
207
|
}
|
|
208
|
-
function transitionDependencies(
|
|
208
|
+
function transitionDependencies(_availability, activation, dnsEvidence, dnsRecords, tlsEvidence) {
|
|
209
209
|
const dnsComplete = sourceComplete(dnsEvidence);
|
|
210
210
|
const nameservers = strings(dnsRecords.ns);
|
|
211
211
|
const addresses = [...strings(dnsRecords.a), ...strings(dnsRecords.aaaa)];
|
|
@@ -383,7 +383,7 @@ export function buildAcquisitionDueDiligence(input) {
|
|
|
383
383
|
policyChecks,
|
|
384
384
|
nextSteps,
|
|
385
385
|
limitations: [
|
|
386
|
-
'This workspace
|
|
386
|
+
'This workspace organises observed evidence; it does not value a domain or establish that it can be acquired.',
|
|
387
387
|
'Expiry dates, EPP statuses, sale signals, and contact routes can change after collection.',
|
|
388
388
|
'WHOISleuth does not assess legal rights, registry eligibility, registrar terms, escrow, tax, or payment risk.',
|
|
389
389
|
],
|