This policy covers COVCOM and its cryptographic dependency leviathan-crypto, both maintained by the same author and released in tandem. Support is rolling, so only the current release is supported. A vulnerability in either project triggers a coordinated release that immediately deprecates the previous version.
| Version | Status | Reason |
|---|---|---|
| v3.1.0 | ✓ supported | Latest version |
| v3.0.0 | ✗ deprecated | insufficient rendering sanitization |
| v1.0.0 | ✗ deprecated | XChaCha20 seal wasn't key-committing, thus vulnerable to salamander style partitioning-oracle attacks |
| v0.0.1 | ✗ deprecated | public beta |
Caution
Deprecated versions receive no patches. Upgrade promptly.
Deprecation lands on every channel at once: the outgoing Docker tag is
replaced by a tombstone image, and the outgoing covcom and
covcom-server npm versions are deprecated in lockstep with the same
reason string.
The standalone server and CLI binaries embed the Bun runtime they were
compiled with. A Bun security fix that touches the network, TLS, or WebSocket
stack does not reach a published binary until the project rebuilds it, so a
relevant Bun security release triggers a COVCOM patch release. The rolling
policy above covers the rest: only the current release's binaries are
supported, and the current release always carries the current runtime.
The npm platform packages (@covcom/cli-*, @covcom/server-*) wrap these
same binaries and carry the same frozen runtime, so the policy covers them
identically.
The other run modes patch on their own channels. Source mode picks up Bun fixes when the host's bun updates; the Docker image picks them up on each image rebuild.
Important
Please do not open a public issue for security vulnerabilities.
Use GitHub's private vulnerability reporting form: https://github.com/xero/covcom/security/advisories/new
This opens a private channel between you and me, and you will receive a response promptly. If the vulnerability is confirmed, we will collaborate to fully understand the issue, including a review of proposed fixes, so you can track and validate firsthand. Before any public advisory is published, we will agree on a coordinated disclosure timeline. After disclosure, you are encouraged to publish your own write-up, blog post, or research notes, for full hacker scene credit.
If you prefer to contact me directly:
- Email: x﹫xero.style · PGP:
0xAC1D0000 - Matrix: x0﹫rx.haunted.computer
Note
Encrypted communication is welcome and preferred for sensitive reports.
In scope:
- Vulnerabilities in COVCOM's web client, CLI, or server
- Vulnerabilities in the COVCOM wire protocol or session handshake
- Cryptographic weaknesses in the ratchet implementation or key derivation
- Vulnerabilities in leviathan-crypto primitives or the WASM layer
- Protocol design flaws (an unsound design itself counts)
- Dependency vulnerabilities that affect COVCOM's security properties
- Invite format weaknesses (enumeration, forgery, replay)
Out of scope:
- Bugs in leviathan-crypto unrelated to COVCOM's use of it. Please report those in the leviathan-crypto repository
- The non-goals listed in the threat model: endpoint security, traffic analysis, server availability attacks, multi-session correlation
- Attacks requiring physical access to a participant's device
- Social engineering attacks against participants
- APT-level nation-state adversaries with quantum computing capability today (ML-KEM-768 addresses future quantum, not present-day state actors with unlimited classical resources)
- Spam or denial-of-service against publicly hosted instances
All cryptographic operations in COVCOM are provided by leviathan-crypto, a zero-dependency TypeScript/WASM library by the same author. There are no third-party cryptographic dependencies.
The active primitive set:
| Primitive | Purpose |
|---|---|
| XChaCha20-Poly1305 | Message and file encryption |
| ML-KEM-768 (FIPS 203) | Post-quantum key encapsulation |
| HKDF-SHA-256 | Key derivation throughout |
| Seal+MlKemSuite | Chain seed distribution |
| Ed25519PreHashSuite | Identity-claim and per-message signing |
| BLAKE3 | Identity-log chain hash and fingerprint derivation |
| SHA-256 Merkle | Per-sender transcript log |
The protocol implements the Sparse Post-Quantum Ratchet from the Signal Double Ratchet spec (§5, Revision 4) with a Sender Keys group messaging model.
Tip
The cryptography reference documents how each primitive is constructed and composed. The protocol specification covers the wire format, session handshake, and ratchet flow.
Message confidentiality. Passive and active network adversaries learn nothing from the wire.
Forward secrecy. Past messages stay unrecoverable from current state.
Post-compromise security. State heals at every KEM ratchet boundary.
Harvest-now-decrypt-later resistance. ML-KEM-768 guards against future quantum decryption.
Enumeration resistance. A 2^128 room secret space defeats guessing.
Session anonymity. No persistent identity keys are visible to the server.
Per-message provenance. Every broadcast carries a detached Ed25519 signature, verified before AEAD, over the signed bytes counter || epoch || sender || ts || ciphertext.
Split-view detection. Each peer's identity claims form a BLAKE3-chained log, surfaced as an 8-colour fingerprint for out-of-band comparison.
Untrusted-content rendering. Peer-controlled display text (usernames, message bodies, filenames) never becomes markup in the web client or terminal escapes in the CLI. This defeats XSS, terminal escape injection, and bidi or homoglyph display-name spoofing.
Validated client configuration. The CLI parses its config file defensively. Theme colors must match a closed set of forms (ansi16 0-15, 256 0-255, or #rrggbb hex), so a config value can never reach the terminal as an arbitrary escape sequence through the color path. An invalid value falls back to its slot default instead of emitting a broken escape, and a config file that fails to parse falls back to defaults rather than being silently discarded. The ignored settings are named in a modal on launch, so the problem is visible instead of manifesting as garbled output.
Clean teardown. Session keys live only in memory and are wiped on every exit path (Ctrl+C, /exit, SIGTERM, and fatal errors), not just a graceful disconnect. The CLI also restores the terminal on the way out, leaving no chat transcript on screen or in scrollback.
Endpoint compromise. Malware or physical device access defeats any transport security.
Traffic analysis. Timing, message volume, and session duration stay observable.
Membership lies. A malicious server can misreport who is in a room.
Cryptographic deniability. Signatures bind authorship, so messages are not deniable.
Multi-session correlation. Out-of-band means can still link separate sessions.
Note
See the full Dolev-Yao style adversary analysis in THREAT-MODEL.md.
The protocol's guarantees are cryptographic and hold against the network. The Docker image adds a hardened transport and delivery layer on top, so a default deployment does not weaken them.
Automatic TLS. Caddy terminates TLS and provisions a certificate over ACME
for $DOMAIN on first start. Plain HTTP on port 80 redirects to HTTPS. The
certificate and ACME account live on the covcom_caddy_data volume, so a
restart reuses them instead of re-provisioning and tripping Let's Encrypt rate
limits.
Single-origin relay. The container serves the web client and proxies the
WebSocket relay on one origin. The client derives the socket scheme from the
page it loaded, so an HTTPS page always connects over wss:// and never falls
back to plaintext ws://.
Strict Content Security Policy. The built client ships default-src 'none'
with no worker-src, a hashed inline script instead of 'unsafe-inline', and a
connect-src confined to the same origin, wss:, and loopback ws://. All
cryptography runs as main-thread WASM under wasm-unsafe-eval; no worker is
spawned. COVCOM is the single-file SPA worked example in
leviathan-crypto's CSP reference, which covers the full policy and
its rationale.
Clickjacking protection. Caddy sends X-Frame-Options: DENY. The equivalent
frame-ancestors directive is silently ignored when delivered in a <meta>
CSP, so the protection is enforced as a real response header.
Runtime-only configuration. The image takes no build arguments. Secrets such
as ADMIN_TOKEN are passed as runtime environment variables and are never baked
into an image layer. The runtime image carries no build or development tooling.
Warning
The TLS termination and the X-Frame-Options header come from the bundled
Caddy, not the Bun server. If you run the server directly behind your own
reverse proxy (the no-docker path), you must terminate TLS and set the
equivalent security headers yourself.