Zero-Trust Vulnerability Reporting — ciphertext-only delivery.
BLT-Zero is a Cloudflare Workers site that lets security researchers submit sensitive vulnerability reports encrypted in the browser using the target organization’s public key. The Worker receives ciphertext only, forwards it to the organization’s security inbox, and stores only minimal metadata.
It is an independent application under the OWASP BLT project family, intended to run on its own deployment and database.
BLT-Zero provides a zero-trust workflow for delivering vulnerability reports securely:
- Encryption happens client-side (browser) using the Web Crypto API.
- BLT-Zero never receives plaintext vulnerability details.
- Organizations decrypt locally using their private key.
| Principle | Description |
|---|---|
| Ciphertext-only server | Worker receives only an encrypted JSON package (no plaintext). |
| Org-only decryption | Reports are encrypted to the organization’s public key; only their private key can decrypt. |
| Minimal metadata | Only domain, optional username, hash, and timestamps are stored in D1. |
| No tracking by design | No analytics/cookies/fingerprinting in this project. |
| Abuse controls | Rate limiting + optional Cloudflare Turnstile. |
-
Client (Browser)
- Builds the report JSON in memory
- Encrypts it using P-256 ECDH + HKDF(SHA-256) + AES-GCM
- Sends only the encrypted package to the Worker
-
Worker (TypeScript)
- Validates request + (optional) Turnstile
- Looks up the org public key for the domain from D1
- Emails the encrypted JSON package to the org inbox (SendGrid or MailChannels)
- Stores minimal metadata in D1 (no report content)
-
D1 (SQLite)
domains: domain → org email + org public key (JWK) + key_idsubmissions: submission id + domain + optional username + artifact hashrate_limits: simple per-IP minute bucket counters
Client-side encryption
- Org publishes a P-256 public key (JWK) to BLT-Zero (admin onboarding).
- Browser generates an ephemeral P-256 keypair, performs ECDH, derives AES key via HKDF, encrypts with AES-GCM.
- Output is a JSON “package” containing:
eph_pub_jwk,salt,iv,ciphertext,key_id,domain, etc.
Decryption
- Organization uses the private key locally with the provided
tools/org_decrypt.py - Produces
report.json(plaintext) on the org side only.
- 🔒 End-to-end encryption in the browser (Worker never sees plaintext)
- 📧 Direct delivery to org security inbox (ciphertext attachment)
- 🧾 Minimal storage: domain + optional username + artifact hash only
- 🧑💼 Org onboarding page to register domain + public key and optionally send onboarding email
- 🧰 Tools
tools/org_keygen.py– generate org keypair locallytools/org_decrypt.py– decrypt incoming packages locally
- 🛡️ Rate limiting
- 🧩 Optional Turnstile
- Can be disabled for local dev using
DISABLE_TURNSTILE=true
- Can be disabled for local dev using
- 📊 Optional points sync to main BLT
- Org admin generates keypair locally (private stays with org).
- Org admin onboards domain + public key into BLT-Zero (
/admin/onboard). - Reporter submits report → browser encrypts → Worker receives ciphertext only.
- Worker emails ciphertext JSON attachment to org inbox + stores minimal metadata.
- Org decrypts locally using
tools/org_decrypt.py.
- Runtime: Cloudflare Workers
- Worker Language: TypeScript (best fit for Web Crypto + performance)
- Crypto: Web Crypto API (ECDH P-256 + HKDF + AES-GCM)
- DB: Cloudflare D1
- Email: SendGrid (recommended) or MailChannels
- Protection: optional Turnstile + rate limiting
- Clone the repository:
git clone https://github.com/OWASP-BLT/BLT-Zero.git
cd BLT-Zero- Install Wrangler (if not already installed):
npm install -g wrangler- Login to Cloudflare:
wrangler login- Create the D1 database:
wrangler d1 create blt_zero-
Create
.dev.varsfile from.dev.vars.exampleand populate wrangler.toml with Database ID from previous step: -
Apply database migrations:
# For local development
wrangler d1 migrations apply blt_zero --local
# For production (remote database)
wrangler d1 migrations apply blt_zero --remoteRun the development server:
wrangler devThe application will be available at http://localhost:8787
Deploy to Cloudflare Workers:
wrangler deploy- Generate organization keypair locally:
python tools/org_keygen.pyThis will generate:
private_key.jwk(keep this secret)public_key.jwk(share this with BLT-Zero)
- Decrypt a received vulnerability report:
python tools/org_decrypt.py private_key.jwk package.jsonBLT-Zero is part of OWASP BLT Project #79 — Zero Trust Vulnerability Reporting.
Contributions are welcome! Please:
- Check the open issues for tasks to work on.
- Fork the repository and create a feature branch.
- Submit a pull request referencing the relevant issue.
Please follow the OWASP BLT contribution guidelines.
This project is licensed under the GNU Affero General Public License v3.0.