Security proof.
We do not prevent screenshots — that claim is not verifiable. What follows is what we do instead, proved by regenerable artifacts from automated tests. Glossary.
16
Attestations
13
Passing
1
In progress
2
Under investigation
scripts/e2e.sh attestation && scripts/proof-publish.shA per-Recipient invisible payload is embedded at serve time. Any leaked copy maps back to the specific Recipient whose Share produced it — without requiring cooperation from the platform it leaked on.
Forensic Watermarking
upload→share→serve→trace returns matched:true with recipient_label matching the share-time value AND trace receipt verifies VALID

trace-response.json ↓
{
"matched": true,
"hash": "1445fce",
"recipient_label": "Recipient A"
}receipt.json ↓
{
"receipt": {
"version": 1,
"kid": "v1",
"signed_at": "2026-04-17",
"server_identity": "ownly-test",
"signature": "8b382d643e785faeeb6a773087d71a069ae1623375b397cc5df734a40cdbfcde"
},
"payload": {
"hash": "1445fce",
"recipient_label": "Recipient A"
}
}Trace Receipt
exit 0 AND stdout contains Verdict VALID
Test outputs ↓
{
"exit_code": 0,
"stdout_first_500_chars": "Verdict: VALID\nReason: none\n\nContent ID: 20260415-95ca9058\nRecipient: prod-receipt-fixture\nHash: 634df1b\nGrant ID: 670fefdf-e39e-43d0-b3a0-b33e6821a177\nShared at: 2026-04-15T19:21:18.235618+00:00\nSigned at: 2026-04-15T20:01:08.984Z\nSigned by: ownly-test (kid=v1)\nSignature: 4efb0edec9707f84…\n",
"stderr_first_500_chars": ""
}Verify offline
node scripts/verify-receipt.mjs web/public/proof/snapshots/trace-receipt/
Honeypot Variations
Different grant_ids produce different variation_seeds AND different served bytes (SHA-256 differs per-Recipient); re-query returns same seed (determinism).
Investigation open — /trace · contact us for status.
Test outputs ↓
{
"hash_alice_prefix": null,
"hash_bob_prefix": null,
"bytes_differ": false,
"seeds_differ": true,
"determinism_holds": false
}Canvas Fingerprint
Posting a different fingerprint hash to /api/grant/fingerprint sets fingerprint_mismatch=true AND does NOT overwrite device_fingerprint (first-seen preserved, route.ts:125-130); POST /api/grant/fingerprint payload matches view_grants.device_fingerprint (64-char SHA-256 hex); repeat-view mismatch detection documented
Test outputs ↓
{
"mismatch_flag_set": true,
"device_fingerprint_preserved": true,
"mismatch_flag": false,
"round_trip_match": true
}Client-side mechanisms shipped as JavaScript that every Recipient already receives. Attribution Overlays, Hold-to-View gating, Temporal Noise, and Content-Aware Noise raise the effort required to produce a clean, redistributable screenshot.
Hold-to-View
initial state shows blurred placeholder; mousedown reveals content; mouseup blacks out within 50ms
Attribution Overlay
DOM timer-bar contains recipient_label AND canvas screenshot captured

Temporal Noise
≥30% of pixels differ by ≥5 between consecutive noise frames when hold_to_view_enabled=false (noise loop starts automatically after auto-render); ≥30% of pixels differ by ≥5 between consecutive noise frames (noise present); 2-frame average has lower or equal variance than single frame (noise cancels)
Content-Aware Noise
mean noise magnitude in top-30% saliency bin ≥ 1.2× mean noise magnitude in bottom-30% saliency bin (saliency-modulated amplitude confirmed active)
View Treatment
Share with custom view_treatment (opacity=0.05, amplitude=5, hold=true) succeeds (200) and viewer holds-to-view correctly; view_treatment wiring from /api/share to Secure Viewer confirmed; POST /api/share with attribution_overlay_opacity=0.5 (above [0, 0.3] range) returns 400 with error array

Tooling that activates after a Leak is identified. Both mechanisms are in progress — their current status is surfaced honestly rather than hidden.
Capture Response
canvas pixel sample changes on synthetic visibilitychange event
Investigation open — see spec · /trace · contact us for status.
DMCA Notice
Given a successful Leak Trace (with Trace Receipt) and a Share Capability Receipt, /api/trace/notice generates a §512(c)(3)-compliant DMCA Notice with all required fields populated and both cryptographic signatures embedded; the HTML output contains the Recipient label, watermark hash, and both receipt signatures.
Not yet implemented. See spec.
Test outputs ↓
{
"skip_reason": "trace returned matched:false — watermark service cold or sample image has no embedded watermark. Use a watermarked copy from the share URL."
}Metadata scrubbing, access quotas, authentication gates, signed Receipts, and Protection Profiles. Less visible than the layers above — load-bearing for every claim on this page.
Metadata Scrub
no tag from the denylist present in exiftool -j output on the stored Blob
Access Control
first view status==200 AND second view status==403 with body 'View limit reached'
Trace Bearer Auth
status==401 AND bearer token is not leaked in response body
Capability Receipt
Share creation emits a Capability Receipt with a valid HMAC-SHA-256 signature over the Protection Profile payload; the verify endpoint confirms valid: true; a corrupted signature is rejected with valid: false.
Protection Profile
Share creation for an image/jpeg Content resulted in protection_profile_id='standard-image' on the view_grants row.









