Security posture
This server distributes software to routers that sit between households and the internet. It is written on the assumption that it will eventually be compromised, and arranged so that when it is, the damage is bounded.
What a compromise of this server gets an attacker
- Withholding. They can stop serving an update. Devices keep the version they have and their last-check time stops advancing, which the admin panel surfaces.
- Corruption. They can serve garbage. Devices reject it at the signature check, before anything is unpacked.
- Traffic analysis. They see which addresses fetch which versions. Logs are truncated to /24 and /48 for that reason.
- Transport impersonation, if they also take the Ed25519 identity key. Sessions from that point on can be spoofed; past sessions cannot be read, because their secrets came from ephemeral keys.
What they do not get is the ability to publish a release. The SLH-DSA signing key is never on this host.
Controls
| Risk | Control |
|---|---|
| Broken access control | Nothing is behind a login because nothing here is private. The one privileged action - publishing - happens out of band, on the filesystem, never over HTTP. |
| Path traversal | URLs are never mapped onto the filesystem. A request path is looked up in an allow-list built from the verified manifest, so a file that is not in a manifest is unreachable regardless of encoding. |
| Cryptographic failures | HTTPS only, HSTS, hybrid X25519 + ML-KEM-768 sessions, HKDF-SHA-384, AES-256-GCM, constant-time MAC comparison. |
| Injection | No database and no shell. OpenSSL is invoked as an argument vector, never through a shell. Templates autoescape; the site renders no user input beyond validated path segments. |
| XSS | The site ships no JavaScript, and the CSP is default-src 'none' with only same-origin CSS, fonts and images. Artifacts are served as application/octet-stream with nosniff, so an uploaded file can never render as markup. |
| CSRF / session fixation | No cookies, no sessions in the browser sense, no forms. There is nothing to forge a request into. |
| Security misconfiguration | Start-up refuses to proceed without keys; a channel that fails verification is withdrawn and /ready reports 503. Interactive API docs are disabled and the server banner is fixed. |
| Host-header injection | Requests whose Host is not the configured domain get 421. Absolute URLs are built from configuration, never from the request. |
| Denial of service | Per-IP token buckets, with a separate and much smaller bucket for key exchange because each handshake forks OpenSSL. Bounded session table, bounded client table, capped request bodies. |
| Logging failures | One structured line per request. Control characters in paths are neutralised so a request cannot forge a log line. Client addresses are truncated. |
| Information disclosure | Tracebacks are never returned. Validation errors name the offending field but never echo its value. A missing channel and a missing file return the same 404. |
Post-quantum posture
Release provenance is hash-based (SLH-DSA-SHA2-128s, FIPS 205) and therefore already quantum-resistant.
Session key exchange is hybrid X25519 + ML-KEM-768 (FIPS 203), so recorded traffic cannot be decrypted later by an adversary with a quantum computer.
Reporting a vulnerability
Contact details are in /.well-known/security.txt (RFC 9116). Please include enough detail to reproduce. We will confirm receipt, and we will tell you when a fix ships and in which release.