Evidence anyone can check offline

Every Settlens JSON report carries a SHA-256 digest of its own content. Sign that digest with an ed25519 key and a customer, partner or auditor can confirm, with no network access, that the report is intact and was attested by the key you published.

Real output from an attested scan of the demo target.

settlens evidence verify
settlens evidence verify attestation.json \
    --report reports/settlens-cb29c023.json
VALID evidence attestation
Signature valid: true
Report matches:  true
Public key:      0x07275b21a0307d196228262603b7b16844487c1db1ce1dd0244c5ab9c9612fed

In short

Every Settlens JSON report carries a SHA-256 digest of its canonical content. settlens evidence attest signs that digest, the report id and a timestamp with your ed25519 key, so a customer or auditor can verify offline that the report is intact and which key attested it.

Two layers of proof

The integrity digest comes with every JSON report. The attestation is optional: it adds a signer and, because the digest is signed, makes deliberate edits detectable.

Integrity digest and signed attestation
PropertyIntegrity digestSigned attestation
Detects accidental changes to the JSON report
Detects a deliberate editNo: whoever edits the report can recompute itYes, with --report: the signed digest no longer matches
Says who vouches for the reportThe holder of the signing key
Carries a timegeneratedAt, inside the reportattestedAt, signed
Needs a key to createAn ed25519 private key
Verifiable offline
Commandverify-reportevidence verify

How it works

The signer keeps the private key. The verifier needs only the attestation, the report and the expected public key.
  1. Scan

    Any scan or check writes a JSON report. Settlens serializes it with sorted keys (settlens-stable-json-v2), hashes it with SHA-256 and stores the result in an integrity block.

  2. Generate a key once

    evidence keygen creates an ed25519 key pair with Node's built-in crypto. With --out, it writes the private key to a new file readable only by its owner, and refuses to overwrite a file that already exists. Publish the public key where your verifiers can find it.

  3. Attest

    evidence attest works offline: it signs the report's digest, id, product and protocol versions, subject URLs, summary, a timestamp and your public key. It signs the digest recorded in the report without recomputing it, so run verify-report first.

  4. Share and verify

    Send the report and attestation.json. evidence verify checks the signature, with --report that the report is intact and is the one attested, and with --expect-key that your key signed it.

Producing evidence
settlens verify-report reports/settlens-cb29c023.json
VALID Report content matches its SHA-256 evidence digest.
Expected: 3c101d12204a09a63dcbb2605ee160b40f09e6444e49a7ecb7fee2738bcde126
Actual:   3c101d12204a09a63dcbb2605ee160b40f09e6444e49a7ecb7fee2738bcde126
settlens evidence keygen --out settlens-evidence.key
Private key written to settlens-evidence.key (keep it secret).
Public key: 0x07275b21a0307d196228262603b7b16844487c1db1ce1dd0244c5ab9c9612fed
settlens evidence attest reports/settlens-cb29c023.json \
    --key settlens-evidence.key --out attestation.json
Attestation written to attestation.json

What an attestation contains

JSONattestation.json
{
  "kind": "settlens-evidence-attestation",
  "version": 1,
  "canonicalization": "settlens-stable-json-v2",
  "reportId": "cb29c023",
  "productVersion": "0.5.0",
  "protocolVersion": 2,
  "subjects": [
    "http://127.0.0.1:4402/secure"
  ],
  "summary": {
    "pass": 23,
    "fail": 0,
    "warn": 0,
    "skip": 0
  },
  "reportDigest": "3c101d12204a09a63dcbb2605ee160b40f09e6444e49a7ecb7fee2738bcde126",
  "attestedAt": "2026-10-13T11:12:36.225Z",
  "publicKey": "0x07275b21a0307d196228262603b7b16844487c1db1ce1dd0244c5ab9c9612fed",
  "signature": "0xda54e746e5adabc6a4726ca3c794b488823fa4bcece60df585a17e8791c51bbc668ba1dba5a5aa5a7b009067b74d7bfc87a982f47cc7d95602557df88402f905"
}
Attestation fields
FieldMeaning
reportDigestThe report's SHA-256 integrity digest: the link to the exact report.
canonicalizationThe canonical JSON form that was signed, settlens-stable-json-v2.
reportIdThe report's id, also part of its file name.
subjectsTarget URLs from the report, as sanitized in it.
summaryPass, fail, warn and skip counts.
productVersion, protocolVersionSettlens version and x402 version of the report.
attestedAtWhen the signer attested, from the signer's clock.
publicKeyThe raw 32-byte ed25519 public key, hex.
signatureed25519 signature over every other field, in sorted-key JSON.

What an auditor can check offline

Questions an auditor can answer with the files alone
QuestionHowCommand
Is the report internally consistent?Recompute the canonical SHA-256 digest and compare it with the integrity block. This catches corruption and careless edits, not someone who recomputes the digest.settlens verify-report report.json
Is this the report that was attested, unchanged?The report's digest must equal the attestation's reportDigest, which the signature protects.settlens evidence verify attestation.json --report report.json
Was the attestation changed?The ed25519 signature must verify over every attested field.settlens evidence verify attestation.json
Who attested it?Pass the key the signer published, obtained through a channel you trust. An attestation signed by any other key is INVALID.settlens evidence verify attestation.json --expect-key signer.pub
Did the assessment move funds or use keys?The report scope declares settlementCalls: 0 and privateKeysUsed: 0. These are fixed by design, since Settlens has no code path that settles or signs a payment, not measured during the run.Read the report
Was an active probe authorized?Active targets record mode: active-authorized and the approval reference.Read the report

What tampering looks like

Each layer catches a different edit. All three transcripts are real.

Editing the report
# one check message edited in the report
settlens verify-report tampered.json
INVALID Report content was modified after the evidence digest was created.
Expected: 3c101d12204a09a63dcbb2605ee160b40f09e6444e49a7ecb7fee2738bcde126
Actual:   59171055343d2f48b64a85efe2fd4b490da979add667ef5762880572c7192014
settlens evidence verify attestation.json --report tampered.json
INVALID evidence attestation
Signature valid: true
Report matches:  false
Public key:      0x07275b21a0307d196228262603b7b16844487c1db1ce1dd0244c5ab9c9612fed
Reasons:
  - The provided report failed its own integrity check.
Editing the attestation
# the subject URL edited in the attestation
settlens evidence verify attestation-edited.json --report reports/settlens-cb29c023.json
INVALID evidence attestation
Signature valid: false
Report matches:  true
Public key:      0x07275b21a0307d196228262603b7b16844487c1db1ce1dd0244c5ab9c9612fed
Reasons:
  - The attestation signature is invalid.
A valid signature from someone else
# the same report, attested with a different key
settlens evidence verify attestation-other.json --report reports/settlens-cb29c023.json
VALID evidence attestation
Signature valid: true
Report matches:  true
Public key:      0x272957df36966f378990ec667b94757c5a08939c28cc63c2336437159d05ee1f
# the same check, pinned to the key you published
settlens evidence verify attestation-other.json --report reports/settlens-cb29c023.json \
    --expect-key ours.pub
INVALID evidence attestation
Signature valid: true
Report matches:  true
Expected signer: false
Public key:      0x272957df36966f378990ec667b94757c5a08939c28cc63c2336437159d05ee1f
Reasons:
  - The attestation is signed by 0x272957df36966f378990ec667b94757c5a08939c28cc63c2336437159d05ee1f, not by the expected key 0x07275b21a0307d196228262603b7b16844487c1db1ce1dd0244c5ab9c9612fed.

Always check the public key

The public key travels inside the attestation, so anyone can attest any report with their own key and the signature will verify. What makes an attestation yours is that its publicKey matches the key you published. Verifiers should pass that key with --expect-key, as the last command shows, or compare it by hand.

What the report records, and what it leaves out

The digest covers the whole JSON report: scope, summary, every target and every check with its message and evidence. Reports are designed to be shared:

  • In target URLs, credentials are removed and common secret query parameters (tokens, keys, signatures) are redacted.
  • Request headers are recorded by name only, never by value.
  • The paid resource's response body is never stored: only its size and SHA-256 digest. Facilitator capabilities read from /supported are kept as evidence.
  • The scope records how many targets were probed actively and declares zero settlement calls and zero private keys used.

Read more in the report reference and the methodology.

JSONsettlens-cb29c023.json (top level, targets elided)
{
  "schemaVersion": 1,
  "reportId": "cb29c023",
  "product": "Settlens",
  "productVersion": "0.5.0",
  "protocol": "x402",
  "protocolVersion": 2,
  "integrations": { "officialX402Core": "2.28.0" },
  "generatedAt": "2026-10-13T11:12:36.003Z",
  "scope": {
    "targetCount": 1,
    "activeTargetCount": 0,
    "settlementCalls": 0,
    "privateKeysUsed": 0
  },
  "metadata": { "source": "cli" },
  "summary": { "pass": 23, "fail": 0, "warn": 0, "skip": 0 },
  "targets": [ … ],
  "integrity": {
    "algorithm": "sha256",
    "canonicalization": "settlens-stable-json-v2",
    "digest": "3c101d12204a09a63dcbb2605ee160b40f09e6444e49a7ecb7fee2738bcde126"
  }
}

Verification from an agent

The Settlens MCP server exposes the same checks as offline tools: verify_report recomputes a report's digest and verify_attestation checks an attestation's signature, given the report that it is the one attested, and given expected_public_key that the expected key signed it. An agent can confirm a counterparty's evidence before relying on it, with no network access and no key.

What evidence does not prove

  • Identity is a key, not a name. There is no certificate authority, registry or revocation. Publish your public key somewhere verifiers trust, and rotate it yourself if it leaks.
  • The time is the signer's. attestedAt comes from the signing machine's clock. It is signed, but it is not a trusted timestamp.
  • JSON only. The digest covers the JSON report. The HTML and SARIF files are renderings of the same run and are not signed.
  • Observed behavior, not certification. An attestation says what Settlens observed during the run. It is not a security audit, a compliance certificate or legal advice.
  • Your key, your custody. Settlens never stores evidence keys. Keep the private key out of repositories and CI logs; a leaked key can attest anything.

Questions about evidence

Does verification need Settlens servers or a network connection?

No. verify-report and evidence verify run locally on the files. The signature check uses Node's built-in ed25519 implementation.

What exactly is signed?

A JSON object with sorted keys containing the canonicalization name, the report digest, report id, product and protocol versions, subject URLs, summary counts, attestedAt and the public key. The signature covers all of it.

Can I verify an attestation without the report?

Yes, the signature can be checked alone. You then know the attestation is intact, but not whether a given report is the one attested; pass --report for that.

Where should I publish my public key?

Anywhere your verifiers already trust: your website, a security page, a signed email or a contract annex. Verifiers pass it to evidence verify with --expect-key, or compare it with the publicKey field.

Is the integrity digest enough on its own?

No. It catches corruption and careless edits, but anyone who edits the report can recompute it, and it does not say who produced the report. An attestation signs the digest, so verifying the report against it detects edits and identifies the signer.

Sources

  1. RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)IETF · rfc-editor.org
  2. FIPS 180-4: Secure Hash Standard (SHS)NIST · nvlpubs.nist.gov

Get a report you can hand to a partner

A pilot ends with a signed assessment of your endpoint that your customers and auditors can verify on their own machines.