Security & threat model
Updated 2026-10-04
This is the canonical description of how Faraday works. If anything else we publish disagrees with this page, this page wins, and the other one is a bug — please tell us.
Status
- No independent security audit has been done. Everything below describes our design and what we run; none of it has been verified by an outside reviewer yet.
- The source code is not public yet. We targeted Q3 2026 and missed it. There is no new date. Still blocking: secrets fully rotated out of git history, TURN/signaling configs templated so deployment can't leak credentials, and the unlock-code scheme reviewed by an outside cryptographer. Next status update here by 2026-12-31.
- Security researchers can get pre-release source access to review it. Email security@faraday.cam.
If your threat model can't accept “trust the operator,” wait for the source release and an audit.
1:1 calls vs. conferences
The two modes are built differently and protect you differently.
| 1:1 mask call | Conference | |
|---|---|---|
| Face & voice masked on your device | Yes | Yes |
| End-to-end encrypted | Yes | No — encrypted to our media server, which forwards it |
| Other people learn your IP | No — relay-only, no direct fallback | No |
| Our servers see your IP | Yes (TURN relay) | Yes (media server) |
| Man-in-the-middle check | Four spoken words; remote audio muted until confirmed | None |
| Text chat | — | Relayed by media server, not end-to-end encrypted, not stored |
| Who can join | Whoever you give your 6-character code to, while your tab is open | Anyone with the room link |
Threat model
Faraday is designed to protect against
- Account profiling. There is no account, email, phone number, or persistent handle to tie calls together.
- Casual face identification. Your camera image is destroyed by a shader on your device; only the masked frames are sent. Until the person-segmentation model loads, the whole frame is destroyed, so there is no unmasked first frame. If segmentation later stalls for more than 0.6 seconds, the whole frame is destroyed again until it recovers, rather than reusing an old silhouette you may have moved out of.
- Recognising your mask across calls. Every session starts with a new random visual mask and voice setting (from the browser's cryptographic random generator), so your mask doesn't become a persistent pseudonym.
- Casual voice identification. Pitch shift, ring modulation, noise, and bit-crush are applied on your device before audio is sent.
- Your IP address reaching the other person. 1:1 calls are forced through our TURN relay; conferences go through our media server. Peers only ever see our server.
- Us reading 1:1 calls. 1:1 media is end-to-end encrypted, and the four-word check detects a server swapping keys.
- Persistent records. We don't store call content, call history, participant identities, or room records.
Faraday does not protect against
- A compromised device. Malware, a state-grade implant, or a malicious browser extension sees what you see. No website can fix that.
- The other participants. They can record their screen, photograph it, or repeat what you said. Masking is obfuscation, not a guarantee — someone who knows you well may recognise your movement, cadence, or word choice.
- Identifying yourself. Names, places, and details you mention, and anything visible in the background or on a shared screen. Screen share is not masked; the app warns you every time and suggests sharing a single tab.
- Your surroundings. Someone in the room with you, or a camera pointed at you.
- Network-level observers. Your ISP, employer network, or anyone watching your connection can see that you connected to
turn.faraday.cam, when, and how much data flowed. A global passive adversary could correlate timing between two people. For that threat model, use Tor and a separate device. - Us, in conferences. The conference media server handles your (already masked) audio, video, and chat in decrypted form. We don't record it, but you are trusting us not to.
- A leaked conference link. Anyone holding it can join. See Room links & tokens.
How a 1:1 call works
- Your browser generates a random 6-character code with
crypto.getRandomValues. It lives in memory only; reload and it changes. - Your browser registers that code with our self-hosted PeerJS signaling broker on
turn.faraday.cam:443, which holds it in memory only while you're connected so the other person can find you. There is no fallback to any third-party broker. - Your browser fetches short-lived TURN credentials from
/api/turn-creds(HMAC-SHA1, coturnuse-auth-secret, 1-hour lifetime). No static password is in the app. - WebRTC is created with
iceTransportPolicy: "relay": no STUN, no host candidates, only relay candidates on our TURN server (by default TURN over TCP port 3478; the TURN-TLS port has been firewalled, so a network observer can see the TURN control messages, which carry only a random username and expiry, but never the media, which is DTLS-SRTP encrypted end to end). If the relay is unreachable the call fails — it never falls back to a direct connection. - During the call, your browser re-checks the live connection every 2 seconds. It ends the call immediately if your side of the selected path is anything other than a relay candidate, or if a raw camera or microphone track is ever attached to the outgoing connection. The call screen shows RELAY VERIFIED once the check passes.
- Media is encrypted with DTLS-SRTP, with keys negotiated between the two browsers. The relay forwards ciphertext.
- Both screens show four words derived from SHA-256 of both DTLS fingerprints (256-word list, 32 bits). Remote audio stays muted until you confirm they match out loud. A server that swapped keys would produce different words on each side; random success odds are about 1 in 4.3 billion per call.
How a conference works
- Conferences use a self-hosted mediasoup SFU (selective forwarding unit) on
turn.faraday.cam:4443. - Each participant (up to 10) uploads one masked audio/video stream to the SFU. The SFU forwards it to every other participant and to listeners (up to 100), who connect receive-only with no camera or microphone. Nobody has to upload more than their own stream.
- Each browser's DTLS-SRTP session terminates at the SFU, so the SFU sees the masked media in decrypted form in memory. Conferences are not end-to-end encrypted.
- Chat (text only, 500 characters, 1 message/second) is relayed over the same TLS WebSocket and is not stored.
- The first participant in gets a host badge and a mute-all button. Mute-all asks each participant's app to mute itself; it is not enforced by the server. If the host leaves, the badge passes to the next participant. Anyone can raise a hand.
- Listeners get a random two-word handle (e.g. quiet-fern) generated in their browser at join time.
Room links & tokens
A conference link contains the room ID (and, for scheduled meetings, a signed schedule token). Joining goes:
room link ──► /api/conference/token ──► 60-second join token ──► SFU
(bound to room + role) (HMAC-SHA256)| If this leaks | What an attacker can do |
|---|---|
| The room link | Join the room, as a participant or a listener, at any time. Rooms are created on demand, so a room link never expires on the server. The link is the key; there is no password or host approval today. |
| A scheduled-meeting link | Same as above. The schedule token's time window drives the waiting room and countdown in the app; it is not a separate server-side lock on the room. |
| A captured join token | Nothing useful after 60 seconds, and only for the one room and role it was minted for. |
Room IDs are 10 random characters (about 49 bits), so a room can't practically be guessed — the risk is the link being forwarded, screenshotted, or seen in someone's chat history.
So: use a fresh room for each sensitive meeting, share the link only over an encrypted channel, and watch the live participant and listener counts in the room header.
A 1:1 code works the same way — anyone with it can call you while your tab is open — but the four-word check tells you whether the person on the line is talking to you directly.
What each server can see
| Component | Operator | Can see |
|---|---|---|
Website + API (faraday.cam) | Faraday, hosted on Vercel | Request metadata (IP, URL, time). No call content. |
| Signaling broker | Faraday, on Hetzner | Your IP and 6-character code while connected; the WebRTC handshake. No media. |
| TURN relay | Faraday, on Hetzner | Both IPs, timing, and packet sizes of a 1:1 call. Not the content. |
| Conference SFU | Faraday, on Hetzner | IPs, room membership, masked audio/video, and chat, in memory while the room is live. |
Our relay, broker, and SFU are configured not to write per-call or per-room events to logs. That configuration is part of what the future source release and audit need to verify.
What does get written down
“No logs” would be too absolute. Precisely:
- Unlock cookie (paid users only): signed, 30 days, stored in your own browser. Contains a hashed user ID, tier, and expiry.
- Security logs: CSP violation reports, and requests to known attack-scanner paths (
/.env,/wp-admin, …) with IP and user agent. Normal use never hits those paths. - Hosting-provider logs: Vercel keeps its own short-lived platform request logs.
- Server error logs: crashes and errors, without IPs or room IDs.
Nothing else: no call content, no call history, no participant identities, no room records. Full detail in the Privacy Policy.
PANIC
PANIC (or pressing Escape three times) stops your camera and microphone, drops the call, clears this site's local storage, session storage, IndexedDB, and caches, blanks the page, and replaces the URL so Back doesn't restore the call.
It cannot erase:
- anything the other side recorded or saw;
- your browser history entry for having visited faraday.cam;
- records outside the browser — OS logs, network logs, router or ISP records;
- the paid-unlock cookie, which is HTTP-only (clear site data to remove it).
Paying doesn't change your protection
Receiving 1:1 calls and listening to conferences are free. A one-time $4.99 purchase (the paid Android app on Google Play) unlocks starting 1:1 calls and hosting or scheduling conferences. Every protection on this page is identical for free and paying users.
Regulated professions
Faraday has not been through HIPAA, GDPR-processor, or any other compliance review, and we don't sign business associate agreements. Clinicians, lawyers, and other regulated professionals may find the architecture useful, but your organization is responsible for deciding whether it meets your obligations.
Reporting a vulnerability
Email security@faraday.cam. We acknowledge within 72 hours. There is no paid bug bounty yet. See also /.well-known/security.txt.
Changelog
- 2026-10-05 — New random mask and voice every session (previously everyone started from the same defaults, and a look you kept became recognisable).
- 2026-10-04 — Scheduled-meeting room IDs lengthened from 6 to 10 characters (about 30 → 50 bits) to match ad-hoc rooms; links created earlier keep working but are easier to guess, so reschedule sensitive meetings. Conferences now refuse to send a raw camera/mic track. Corrected the TURN transport: by default it is TURN over TCP 3478, not TURN-TLS on 5349. Added an automated privacy test suite that runs on every push.
- 2026-10-04 — 1:1 calls now verify at runtime that the connection is on the relay and that no raw camera/mic track is being sent, ending the call otherwise. The mask destroys the whole frame if segmentation stalls. Screen share shows an unmasked-content warning first and suggests sharing a single tab.
- 2026-10-04 — Page created as the single source of truth. Corrections made across the site to match it: conferences are SFU-based and not end-to-end encrypted; TURN credentials last 1 hour (not 60 seconds); the TURN relay is ours, not PeerJS Cloud; a leaked conference link grants entry; raise-hand, host badge, and mute-all are shipped; source release slipped past Q3 2026; the $4.99 purchase unlocks hosting (there is no separate “Supporter” badge). TURN relay session logging and SFU per-room logging switched off. Listener cap of 100 now enforced by the server.
See also: Privacy Policy · Terms of Service