Security
Last updated 29 September 2026
How it's built
- Client-side encryption. Messages are encrypted in a Web Worker in your browser with
tlock-js0.9.0 (pinned) — theageformat with its key timelocked to drand quicknet. How it works. - Pinned chain. The quicknet public key and chain hash (
52db9ba70e0cc0f6…) are hard-coded. We never trust a relay's/info. Every beacon's BLS signature is verified before use; a forged beacon is rejected and the next relay is tried. - Authoritative unlock time. The round is read from the ciphertext, not from the editable label.
- Nothing stored. Capsules live in the URL fragment or in files you keep. No accounts, no database, no uploads.
- No HTML from capsules. Opened letters are rendered strictly as text. Our build fails if
dangerouslySetInnerHTMLorinnerHTMLappears anywhere in the code. - No third-party scripts. No analytics, pixels, widgets or CDNs. Fonts are self-hosted.
- License proxy.
/api/license/*validates input, rate-limits per IP, times out after 5s, holds no secrets, stores nothing and never logs keys. - Report blocklist. Capsules disabled after a report are listed only as SHA-256 hashes of their ciphertext. The check runs in your browser before any beacon is fetched or anything is decrypted.
Content Security Policy
Every page is served with a strict CSP and related headers:
default-src 'self';
script-src 'self' 'unsafe-inline';
worker-src 'self' blob:;
connect-src 'self' https://api.drand.sh https://api2.drand.sh https://api3.drand.sh https://drand.cloudflare.com;
img-src 'self' data: blob:;
style-src 'self' 'unsafe-inline';
font-src 'self';
object-src 'none';
frame-ancestors 'none';
base-uri 'self';
form-action 'self' https://*.dodopayments.com
Referrer-Policy: no-referrer
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=() …script-src allows inline scripts because Next.js streams page data through small inline script tags on statically generated pages. No script from any other origin can run, and no user content is ever rendered as HTML. The browser can only talk to our own origin and the four drand relays.
In scope
ripenote.com and its API routes (/api/license/*): how sealing and opening work in the browser, license handling, and the Content Security Policy and headers above.
Out of scope
- Dodo Payments, Vercel, Cloudflare and drand themselves — report those to them.
- Denial-of-service or load testing.
- Spam or social engineering.
- Missing best-practice headers with no real impact.
- Self-XSS (a page that only affects the person who typed into it).
No paid bug bounty right now; we'll credit you on this page if you'd like.
If drand were compromised
Opening a letter needs a public drand beacon. If most drand operators colluded, locked letters could be opened early. If drand stopped for good, letters dated after that couldn't be opened. We'd post on status and on our X account, and tell people to keep their .seal files. drand describes its own assumptions in its security model.
How we keep the code safe
- Crypto libraries are pinned (including tlock-js 0.9.0).
- A license and dependency check runs on every build.
- GitHub Dependabot alerts us to known vulnerabilities in dependencies.
- No third-party scripts.
- A strict Content Security Policy, shown above.
Account security
We'll never ask for your license key by phone or DM. Only paste it at ripenote.com/unlock.
Reporting a vulnerability
Email security@ripenote.com with a description, steps to reproduce and the impact you expect. Please:
- give us reasonable time (we aim for 90 days or less) to fix the issue before disclosing it publicly;
- don't access other people's data, degrade the service, or run automated attacks against the license routes;
- don't use social engineering or physical attacks.
We'll acknowledge your report within 3 business days, keep you updated, and credit you (if you wish) once it's fixed. We won't pursue legal action for good-faith research that follows these guidelines.
Issues in drand, tlock or tlock-js themselves should also be reported to the drand team via their repositories.