It works out the fingerprint itself.
An AI model is always handling files: one it edits, a prompt it’s given, a view it shows you and calls a true copy of the original. EMET opens those files directly and works out the fingerprint again from scratch, using SHA-256 (a standard, widely trusted recipe for turning any file into one short, unique fingerprint). Then it compares that to the fingerprint it saved before. The answer comes only from running the same recipe over the same file, never from the system telling you it’s fine. It stands outside the thing it’s checking.
Knowing where a file came from is one thing. It still doesn’t tell you whether the copy the model is looking at right now is unchanged. That’s the gap this closes.Three answers. None of them trusted.
There are exactly three answers it can give (MATCH, DRIFT, UNVERIFIABLE), and there will only ever be three. That’s not a promise written in a comment somewhere; the code is shaped so a fourth answer simply has nowhere to come from. It can never tell you to trust something, because it was never given any trust to hand out.
Don’t take the answer on my word. Watch it flip.
A single character is enough to change everything. Check a file, add one character to it, then ask again. The same core rules have implementations in Python, Rust, Node.js, and Go, with capability-specific conformance coverage stated below.
$ python membrane.py verify demo_sample.txt MATCH demo_sample.txt want=d02206abca2a… got=d02206abca2a… (exit 0) # append one byte to the file, ask the same question $ python membrane.py verify demo_sample.txt DRIFT demo_sample.txt want=d02206abca2a… got=b072d611645e… (exit 1) # one spec, four separate language implementations, CI on every push membrane.py → CONFORMANCE 48/48 vectors pass impl/rust/emet → CONFORMANCE 40/40 supported vectors pass impl/js/emet.js → CONFORMANCE 40/40 supported vectors pass impl/go/emet → CONFORMANCE 35/35 core vectors pass
Change a single character in the file and the answer drops from MATCH to DRIFT. It reads the file itself, not anyone who promises it’s fine.
The shared suite contains 48 vectors: 35 core, 5 receipt, 4 rebind, and 4 evaluation-receipt cases. Python covers all 48; Rust and Node cover 40 with rebind and evaluation-receipt skipped by declared capability; Go covers the 35 core vectors. Honest limit: I wrote all four versions myself, so this demonstrates same-author cross-language agreement, not independent reproduction. See a sample proof-surface report →
Limitations kept visible.
The conformance implementations are same author, so they prove that the rules are clear enough to implement in several languages. They do not prove independent authorship, semantic quality, model quality, or third-party adoption.
Its closed verdict records byte agreement, drift, or inability to verify. A human or downstream process still decides what that result means.
EMET v1.3.0 release evidence.
The current public release is v1.3.0 on GitHub and emet 1.3.0 on PyPI. The GitHub release is public, not draft, and not prerelease; no release assets are attached there. PyPI serves the wheel and source archive.
These same-author implementations demonstrate rule clarity, not independent authorship, semantic quality, regulatory assessment, model assessment, policy endorsement, or third-party adoption. The machine-readable maturity record is security-tools.json.