# Faction — we can’t read your messages.

[Faction Privacy First](/) [Open Faction](https://app.faction.chat) Security · Audit

# Security & audit
Last updated: 2026-05-18

Faction's whole product claim is "the server cannot read your messages." Reports that break that claim get our full attention. This page describes how to send one, what we consider in scope, and how we triage what comes in.

## Reporting a vulnerability

**Do not file a public GitHub issue for a security vulnerability.**

Email [michael@faction.chat](mailto:michael@faction.chat). If you want an encrypted intake channel (PGP, Signal, anything else), email and ask — we will share a key out of band rather than publish one that goes stale.

What to include:

- A short description of the issue and its impact.
- Steps to reproduce, or a proof-of-concept.
- The affected version or commit hash if you know it.
- Whether you've already shared the finding with anyone else.

## Disclosure timeline
48h acknowledge receipt 30d ship a fix for critical findings 90d coordinated public disclosure

The 30/90 targets are for critical findings; lower-severity items move on a longer timeline. Whatever the case, we will tell you the plan and keep you in the loop until disclosure.

## Scope

### In scope

- The Faction desktop client (Tauri + Svelte) in apps/client/.
- The browser client served from the same code base.
- faction_api/ — REST API.
- faction_gateway/ — WebSocket gateway.
- faction_media/ — Rust workspace (SFU, OPAQUE server, MLS, audio DSP, P2P, crypto primitives).
- faction_media_proxy/ — TURN / relay edge service.
- faction_relay/ — NAT-traversal signaling.
- Any cryptographic protocol or key-management flow above the listed services.
- The release pipeline insofar as it could result in unsigned or maliciously-signed binaries reaching users.

### Out of scope

- Third-party plugin code hosted on the plugin developer's own server (the plugin developer's webhook handler, frontend, infrastructure).
- Issues that require physical access to a device and the user's unlocked session.
- "Plugin channels are not E2EE" — this is intentional. The client UI shows a mandatory warning banner. See the whitepaper for the full table of channel types and which are encrypted.
- "Webhook-posted messages are not E2EE" — same intentional design, same UI warning.
- Vulnerabilities in upstream dependencies that have been publicly disclosed and are waiting on upstream patches. Please report those upstream first; let us know if there is a Faction-specific exploitation path we should mitigate before the upstream patch lands.
- Pure cryptanalysis assuming a break of AES-256, ChaCha20-Poly1305, X25519, Ed25519, or the OPAQUE protocol itself. We follow upstream guidance on primitive selection.
- Spam, abuse, or content-moderation requests — these go through the in-product report flow, not the security intake.

## Severity
Severity What it means Example **Critical** Breaks the E2EE confidentiality claim. Compromises private identity or epoch keys. Lets an attacker silently ship a malicious update. Server-side decryption of any E2EE channel; SFrame nonce reuse leaking voice or video; OPAQUE login bypass; updater accepting a manifest whose Ed25519 signature does not verify under the baked-in public key. **High** Authentication bypass, privilege escalation, RCE on a server service, persistent XSS in the WebView, MLS sender forgery accepted client-side. Bypassing JWT auth on a privileged endpoint; CQL injection into Cassandra; XSS in the message renderer; accepting a forged leaf-node signature. **Medium** DoS that takes a single server or feature offline. IDOR exposing metadata. Rate-limit bypass. Missing authorization on metadata endpoints. Reading another server's audit-log id; sending past the documented per-channel rate limit. **Low** Information disclosure of already-public metadata, missing security headers, internal version disclosure, log noise that reveals internal structure. Stack trace in a 500 response; missing CSP header.

## Our own audit process

Faction is pre-1.0. We run internal, code-side audits continuously — every release branch goes through a no-leak sweep that checks each crypto path for plaintext logging, missing authorisation gates, race conditions on credential mutations, and key-handling regressions. Findings are tracked against the release that fixes them.

A formal third-party audit is on the runway before general availability. When it lands, the final report will be linked here.
Verification, not promises Every privacy claim Faction makes maps to a specific file in the codebase. The [whitepaper](/whitepaper) contains the per-claim verification table. Faction is source-available
under PolyForm Noncommercial 1.0.0 so independent reviewers can run the same checks we do.

## Load-bearing files

If you are reviewing the crypto rather than penetration-testing, these are the files that carry the most weight:

- apps/client/src-tauri/src/commands/mls.rs — MLS encrypt/decrypt commands, sender leaf-signature verification.
- apps/client/src-tauri/src/commands/voice.rs — SFrame voice encryption, no-plaintext-fallback enforcement.
- apps/client/src-tauri/src/commands/opaque.rs — OPAQUE client flow.
- faction_media/crates/faction-mls/src/sframe.rs — SFrame key derivation from the MLS epoch exporter.
- faction_media/crates/faction-opaque-server/ — OPAQUE server. Does not have, and cannot derive, the user's password.
- faction_api/src/domains/messages/MessagesRepository.ts — message persistence. Ciphertext blob; no plaintext column.
- apps/client/src-tauri/src/commands/updater.rs — desktop update verification against the baked-in Ed25519 public key.

## Acknowledgments

Researchers who report a real issue and want credit will be listed here after the finding is fixed and disclosure timing is agreed.
