One file. Python 3.8+. No network, no account, no vendor — not even a
pip install.
Download it, read it, keep it. It will still work if this company does not.
A compliance certificate whose only proof is “the vendor's server says it's valid” is worth exactly as much as the vendor's continued existence. That is a poor property for evidence you may need to produce years from now, in front of a regulator, possibly after the company that issued it has gone.
So the check does not require us. Copy this file into your own repository, audit it, run it in ten years. It is short enough to read in full before trusting it, which is the point — we would rather you did not have to take our word for anything.
SHA-256 of aicvs_verify.py — 12bd42e6a6fa5062ba3638cad691202f65ddbd8b28c4dfefc17c77e7cd6a9510
Check it after downloading: python -c "import hashlib;print(hashlib.sha256(open('aicvs_verify.py','rb').read()).hexdigest())"
Every scan exposes a self-contained bundle, unauthenticated:
$ curl -O https://api.aicvs.io/api/v1/scans/<scan-id>/bundle.json $ python aicvs_verify.py bundle.json --source your_file.py \ --public-key <pinned-key> --require-signature AICVS certificate verification ---------------------------------------------------- file decide.py cert hash c4584bfc8a55ddda2cfffc4c47318743... chain AICVS-1.11.0 [ok ] source file matches certificate [ok ] step 1_content_ingest ... step 6_cert_digest [ok ] signature (signed_pinned) VERIFIED -- chain intact, signature is from AICVS.
Exit codes: 0 verified, 1 verification failed, 2 not a readable
bundle — so it drops straight into CI.
The bundle carries the certificate, the evidence chain and the four fields that participate in the fingerprint. It deliberately contains no source code and no finding descriptions: verification should never require publishing the code being verified.
All six chain steps are recomputed from the declared inputs. Change a score, a status, a filename, an article mapping — or delete an inconvenient finding — and a hash stops matching.
With --source, the file's SHA-256 is recomputed and compared to the digest sealed into
step 1. This is what connects a document to a specific artefact rather than to a claim about one.
One byte's difference fails the check.
Certificates carry an Ed25519 signature over the terminal digest. Checked against a pinned key, that establishes AICVS issued it — something a hash chain alone cannot show.
signed_pinned (origin proven),
signed_unpinned (maths only), unsigned (older certificates; integrity still
verifies). Fetch the published keys once from
/.well-known/aicvs-signing-keys.json and commit them
into TRUSTED_KEYS in your copy.
Stated plainly, because a verifier that overstates its own guarantee is worse than none:
Published in full so a third party can implement their own checker without our cooperation. Six SHA-256
steps, each folding in the last. CV is the chain version (e.g. AICVS-1.11.0),
recorded in the bundle so old certificates stay checkable after the format moves on.
| # | Step | Input |
|---|---|---|
| 1 | content ingest | CV|1_content|{filename}|{sha256(file)} |
| 2 | identity binding | CV|2_identity|{scan_id}|{h1} |
| 3 | provenance | CV|3_provenance|{findings_fingerprint}|{h2} |
| 4 | EU mapping | CV|4_eu_mapping|{articles, comma-joined}|{h3} |
| 5 | merkle seal | CV|5_merkle|{h2}|{h4} |
| 6 | cert digest | CV|6_cert|{h5}|{score}|{status}|{filename} |
findings_fingerprint is the SHA-256 of the findings reduced to rule_id,
line, severity and score_impact, sorted by
(rule_id, line) and serialised with sorted keys. Prose is excluded deliberately: reworded
copy in a later release must not invalidate a certificate issued today, but a changed rule, line,
severity or score must. Filename participates in steps 1 and 6, so identical code in two files yields
two distinct certificates.
aicvs-cert-v1|{chain_version}|{scan_id}|{cert_hash}
Domain-separated and context-bound on purpose. Without the prefix a signature could be replayed against
another structure that happens to be a hex digest; without scan_id and
chain_version a valid signature could be lifted onto a different scan sharing a cert hash.
The verifier rebuilds this string itself, so if the two implementations ever diverge, verification fails
rather than passing on trust.
The verifier shares no code with the issuing backend. A checker that imports the thing it checks proves
only that the code agrees with itself. The Ed25519 implementation is vendored from RFC 8032 rather than
imported, because pip install cryptography is a bet on a package index still existing and
still serving a build for your platform — precisely the assumption this tool exists to avoid.
The cost of that independence is drift, so our test suite runs this exact script as a subprocess against real scan output, and asserts it imports nothing from the backend. Tests cover a genuine certificate passing; source binding failing on a one-byte change; tampering with score, status, filename and findings each being caught; a forged bundle signed with an attacker's own key being rejected against the pinned key; and the vendored Ed25519 checked against the reference implementation rather than against itself.
MIT. Vendor it, fork it, ship it inside your own audit tooling. Evidence that outlives the vendor is the entire intent — see our continuity commitment for the rest of that answer.