How AdaptoSecret Works
You have a password, API key, or some other secret you need to send to someone. Email is risky. Slack logs everything. Text messages stick around forever.
AdaptoSecret gives you a safer way: paste your secret, get a link, send that link. When the recipient opens it, they see the secret once. Then it is gone. Not hidden, not archived — deleted from our servers entirely.
The zero-knowledge part
Here is the key thing: we never actually see your secret.
When you create a secret link, your browser generates a random encryption key and uses it to scramble your secret before anything leaves your device. That scrambled data is what we store. The key itself lives in the link, after the # symbol.
That #part of a URL is special: browsers never send it to servers. It stays entirely on your device and the recipient's device. So we receive the encrypted gibberish, but we never receive the key needed to read it.
All we can do is store encrypted data we cannot decrypt, and delete it when someone retrieves it.
Optional passphrase protection
For extra security, you can add a passphrase. The recipient will need to enter it before they can see the secret. This means even if someone intercepts the link, they still cannot read the secret without the passphrase you share separately.
The passphrase protection uses serious cryptography — the same kind used to protect cryptocurrency wallets. It is designed to make brute-force guessing impractical even with powerful hardware.
For Security Teams
Written for CISOs, security engineers, and IT leadership evaluating AdaptoSecret for organizational use. What follows is the security posture as actually shipped, not as aspirationally described.
Trust Model
The zero-knowledge architecture moves the trust boundary to the endpoints. Here is exactly what that means in practice:
What a Full Database Compromise Exposes
If an attacker obtained complete read access to our Neon database, they would have:
- Random 16-character record IDs
- AES-GCM ciphertext with 96-bit IVs
- Creation timestamps, expiration timestamps, view counters
- For passphrase-protected records: wrapped keys, 128-bit Argon2id salts, KDF parameters
They would NOT have any plaintext, nor any key material capable of decrypting the ciphertext. Per-secret encryption keys live exclusively in URL fragments, which by HTTP specification are never transmitted to the server. There is no master key to steal because no master key exists.
For passphrase-protected secrets, an attacker with full database access plus possession of the share URL would still face an Argon2id brute-force against the user-chosen passphrase, parameterized at the OWASP 2023 minimum (m=19MB, t=2, p=1).
Compliance Framework Alignment
The architecture is mapped against five frameworks. These are alignment mappings, not attestations. Formal certification requires third-party audit engagement, which is planned pre-launch.
- SOC 2 Type II: Common Criteria CC1 through CC9 mapped. Security, Availability, Processing Integrity, Confidentiality, and Privacy all addressed architecturally.
- ISO 27001:2022: Annex A controls A.5.15, A.5.29, A.5.34, A.8.5, A.8.9, A.8.10, A.8.12, A.8.24, A.8.26 mapped to implementation.
- HIPAA Technical Safeguards: 45 CFR 164.312 integrity and transmission security satisfied at the crypto layer. Access control and audit trail expand with the Phase 2 account system.
- GDPR: Data minimization, storage limitation, and integrity/confidentiality satisfied by design. Right to erasure is automatic. Right of access to plaintext is architecturally impossible to fulfill, which is documented for data subject requests.
- CCPA: Minimal personal information collected. Right to know returns minimal data. Right to delete is automatic.
Third-Party Security Audit
An independent cryptographic and application security audit is scoped as a pre-launch requirement. Candidate firms under evaluation include Cure53, Doyensec, and Trail of Bits. Scope covers the client-side cryptography, the zero-knowledge property, the atomic consume transaction, CSP and SRI configuration, and rate-limit bypass potential. Audit report will be published or shareable under NDA once complete.
Law Enforcement and Legal Process
In response to a valid subpoena, warrant, or other legal process, AdapToIT can produce:
- Ciphertext and metadata for records not yet purged
- Hashed IP prefix records from rate-limit logs (90-day retention)
- Creation and consumption timestamps for a given record ID
We cannot produce plaintext because we have never possessed the decryption keys. This is an architectural property, not a policy choice, and it applies equally to lawful process, insider threat, and external compromise.
Vendor Security Posture
Our service depends on three managed vendors. Each maintains its own compliance program:
- Vercel (hosting, edge, TLS): SOC 2 Type II, ISO 27001, HIPAA (Enterprise), PCI DSS
- Neon (Postgres database for ciphertext storage): SOC 2 Type II, HIPAA (Business)
- Upstash (Redis for rate-limit counters only, never secret content): SOC 2 Type II, GDPR
Data Retention
- Ciphertext and crypto material: nulled atomically on the final authorized view. Present only during the valid-view window.
- Metadata row (ID, timestamps, view counts): retained up to 24 hours past consumption or expiry, then hard-deleted by cron. No soft-delete, no archive table.
- Rate-limit counters: 60-second TTL in Upstash.
- Application logs: 90 days in Vercel log drain. Contain hashed record ID prefix and hashed IP prefix only. No URLs, no fragments, no plaintext, no ciphertext.
- Database backups of the secrets table: explicitly disabled at the Neon role level. No point-in-time recovery for ciphertext.
Responsible Disclosure
Suspected vulnerabilities: please contact security@adaptoit.com. Do not open public GitHub issues for security matters. We aim to acknowledge reports within 2 business days.
The Tech Geek Stuff
Encryption
All encryption happens client-side using the Web Crypto API. No external crypto libraries for the core encryption path.
- Algorithm: AES-GCM with 256-bit keys
- IV: 96-bit random IV generated fresh for each encryption (GCM standard)
- Key transport: Raw key exported to base64url, placed in URL fragment
- Fragment behavior: Per RFC 3986, the fragment identifier is never sent to the server in HTTP requests
Passphrase Mode (Argon2id)
When passphrase protection is enabled, the URL key is wrapped with a key derived from the passphrase using Argon2id.
- KDF: Argon2id via hash-wasm (WebAssembly implementation)
- Parameters: m=19456 (19 MB), t=2, p=1 — OWASP minimum floor
- Hash length: 256 bits (matches AES key size)
- Salt: 128-bit random, stored with the secret
- Memory hard-fail: Devices reporting
navigator.deviceMemory < 0.5 GBare blocked from passphrase mode rather than silently degrading security
Server-Side Storage
- Database: Neon (serverless Postgres)
- Atomic consume: Single-query read-and-delete using
DELETE ... RETURNING— no race conditions, no double-reads - Max views: Configurable (1, 3, or 10) — decremented atomically on each retrieve
- Expiration: 1 hour, 24 hours, or 7 days from creation
- Purge: Cron job runs every 15 minutes, hard-deletes all expired secrets (no soft-delete)
- 24-hour grace purge: All secrets older than 24 hours past expiry are purged regardless of view state
Rate Limiting
Implemented via Upstash Redis with sliding window algorithm.
- POST (create): 10 requests per minute per IP
- GET (retrieve): 60 requests per minute per IP
- IPv6 handling: Collapsed to /64 prefix (first four hextets) to prevent trivial rate limit bypass via address rotation
- Response: 429 with
Retry-Afterheader
Security Headers
- HSTS:
max-age=63072000; includeSubDomains; preload - CSP:
strict-dynamicwith per-request nonces - Frame protection:
frame-ancestors 'none'(CSP) +X-Frame-Options: DENY - Secret routes:
/s/*and/api/secrets/*get extra-strictReferrer-Policy: no-referrerandCache-Control: no-store
Accepted Tradeoffs
Two CSP relaxations are required by our current stack:
style-src 'unsafe-inline'— Tailwind CSS 4 uses@theme inlinewhich injects styles at runtime. Until Tailwind supports nonce-based style injection, this relaxation is necessary. Style injection is significantly lower risk than script injection.'wasm-unsafe-eval'— Required for WebAssembly compilation of hash-wasm (Argon2id in passphrase mode). This directive permitsWebAssembly.compile()andWebAssembly.instantiate()but does NOT re-enable JavaScripteval(). Browser support: Chrome 97+, Firefox 102+, Safari 15.4+.
Error Response Design
All "not found" conditions — never existed, already consumed, expired — return identical 404 responses with matching headers and body. This prevents attackers from distinguishing between valid consumed secrets and invalid IDs, eliminating an information disclosure vector.
AdaptoSecret is open source. Review the implementation at github.com/TheOtherChrisBrown/adaptosecret.