| name | shadow-attestation-verify |
| description | Verify a Shadow attestation record (Ed25519 or HMAC) without leaving Claude Desktop. Confirms request wasn't tampered, response wasn't tampered, the exact pinned model ran, and the deployment key material matches. Use when a bank auditor hands you a persisted JSON response and asks "is this real." Works cross-language — Python shadow-verify library produces byte-identical results for the same inputs on Python 3.9–3.13.
|
| version | 1.0.1 |
| author | Alex Xiaoyu Ji |
| authors | ["Alex Xiaoyu Ji <xji1@mail.yu.edu>"] |
| license | MIT |
| repo | https://github.com/alex-jb/shadow-mentor |
| tags | ["shadow","attestation","ed25519","hmac","audit","verify","cross-language"] |
| scope | shadow:read |
| depends_on | ["shadow_verify_attestation MCP tool (v1.5.1+)"] |
Shadow Attestation Verify
Cryptographic verification of a persisted Shadow decision, without a network call to Shadow itself.
When to use
The user's request combines all of:
- A JSON attestation object (from
response.attestation) with signature, mode, model_id, request_commitment, output_commitment, completed_at_utc, key_id.
- The original request body Shadow was called with.
- The original response body, with the
attestation field stripped (hashing an attestation into itself is a common wrong path).
- The verification key material — Ed25519 public key PEM for procurement-mode records, HMAC secret for legacy dev mode.
If any of the four is missing, ask for it. Do not fabricate.
What it does
Calls shadow_verify_attestation with the four inputs and returns:
- ok — true if signature verifies + commitments match + key_id + model_id are as pinned. False otherwise.
- reason — plain-English reason if false. One of: request tampered, response tampered, model_id substitution detected, signature invalid, wrong key.
- model_id + key_id + completed_at_utc — surfaced for audit trail.
- interpretation — one sentence a compliance officer can paste into an audit note.
The named invariant
Dictionary hash is bound into the signing payload since v1.5.8. If the reason-code dictionary was swapped between decision time and verification time, the signature will not verify — even with the correct key. This closes the "post-hoc dictionary edit" gap under Reg B / CFPB Circular 2026-03.
Approval boundary
Never surface an attestation-verified-true result to the end user if the underlying verdict is escalate or block. That is a separate approval rule, not a verification rule. This skill only proves cryptographic integrity — it does not decide whether the loan was correctly denied.
If ok: false — halt. This is a tampering signal. Do not surface the underlying tool response. Escalate to security per config/approval-rules.json:attestation-verify-failed with a 1-hour SLA.
Non-goals
- Not legal advice. The verifier says the record wasn't tampered; a licensed attorney says whether the underlying decision was legally defensible.
- Not a signature generator. Verification only. Signing lives on the Shadow deployment.
- Not a private-key operation. This skill only ever touches public keys or HMAC secrets shared with the auditor.
Reference
- Shadow
bin/verify-attestation.mjs — CLI equivalent.
- Shadow
POST /api/verify-attestation — HTTP equivalent.
- Python
shadow_verify library — cross-language equivalent, Python 3.9–3.13 CI matrix.
- RFC 8032 (Ed25519).