The breach stops at the camera.
Cheap PoE cameras are a documented breach vector: hardcoded backdoors, telnet, undocumented outbound telemetry. OpenNVR is built so the camera's flaws stop at the camera — it sits on a network it cannot leave, and everything downstream assumes it is hostile.
What follows is what ships. Where something is on the roadmap, it says so. The full mapping from the published architecture to code is inSECURITY_ARCHITECTURE.md.
01
Two networks, one appliance
The camera LAN is an isolated network with no internet — its interface, addressing, DHCP and discovery subnets are configured in the product's Network tab. The uplink is a second NIC that carries user traffic, with its own deny list. Cameras never route to the uplink; users never route to the cameras. MediaMTX ingests RTSP from the camera side and republishes it to the user side as WebRTC and HLS, over TLS.
- ✓ Camera LAN and Uplink configured in the UI, superuser-only
- ✓ MediaMTX accepts only loopback, RFC1918 and link-local sources — public addresses are refused
- ✓ ONVIF discovery scoped to the subnets you list
Destination Gateway Genmask Flags Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG eth0 # uplink
10.0.4.0 0.0.0.0 255.255.255.0 U eth1 # camera LAN
root@opennvr:~# iptables -L FORWARD
Chain FORWARD (policy DROP)
target prot opt source destination
REJECT all -- 10.0.4.0/24 anywhere
02
Your keys, your certificates
Nothing that unlocks anything is ours to hold.
Camera passwords and cloud-provider tokens sit in a credential vault encrypted at rest with a Fernet key you generate and keep — the server refuses to start with a placeholder, and there is no recovery path through us. Streaming or recording to a remote server runs over a TLS certificate and private key you supply (Customer Keys, BYOK), pasted or uploaded as PEM, superuser-only.
- ✓ No default password; first-time setup is token-gated
- ✓ MFA (TOTP) per account
- ✓ Secrets under 32 characters are rejected at boot
roadmapRecording-at-rest encryption with a TPM tier and a hash-chained audit log are planned (V-004, V-012).
03
Encrypted transport, enforced per camera
Plaintext RTSP is refused, not merely discouraged.
MediaMTX ships with TLS-required RTSPS, encrypted HLS and WebRTC, and RTMP and SRT off. Every camera carries a transport policy — rtsps_required, rtsps_preferred or plaintext_allowed — set by a TLS handshake probe when it is added, and enforced at the one choke point every provisioning path goes through. A camera that fails its policy is marked policy_blocked and never provisioned.
- ✓ rtspEncryption: strict by default
- ✓ Policy enforced on all four provisioning paths
- ✓ Self-signed cert generation when there is no PKI
04
AI that cannot phone home
Two default-deny gates, checked continuously.
deployment_mode=offline and ai_sovereignty=local_only are the defaults. Under them KAI-C refuses to register any adapter declaring network egress, re-checks on every capabilities poll, and de-registers one that starts declaring it later. Model weights are fingerprinted with sha256; a changed fingerprint is audited, and an adapter that gains a new permission stops serving until an operator re-approves it.
- ✓ Sovereignty re-checked every 60 s
- ✓ Fingerprint drift and refusals in the audit log
- ✓ Apps run on a network with no route out unless a host is allowed
05
Who did what, provably
An audit trail you can hand to a regulator.
Every inference carries an X-Correlation-Id from the alert that fired, through the middleware, to the model that ran, and lands in an append-only JSONL log. Access is role-based with per-camera grants — viewers look, operators arm, admins govern — and even the agent's chat tools obey the caller's tier. A device firewall approves or blocks the browsers allowed to reach the UI at all.
- ✓ Correlation ID on every inference
- ✓ Per-camera RBAC, enforced on the WebSocket too
- ✓ Compliance and §889 covered-vendor reports
06
Watching the network and the host
The camera LAN is inspected; the host is patched.
OpenNVR ingests Suricata's eve and fast logs from the host and streams the alerts live in the UI, so a camera that starts talking to a botnet C2 shows up as an alert, not a line in a file nobody opens. The Firmware tab reports the host OS, kernel and BIOS, shows pending security updates, and lets a superuser check and apply them — auto-updates on by default.
- ✓ Live Suricata alert stream
- ✓ Host security updates from the UI
- ✓ Coordinated disclosure with named acknowledgements
roadmapSBOM and cosign-signed builds with CVE cross-referencing are planned (V-011, V-014).
07
Coordinated disclosure
Report privately through a GitHub security advisory. Findings are fixed one commit per issue, credited by name in the project's SECURITY.md, and shipped with the researcher's write-up linked. Access-control and SSRF findings from independent researchers have already landed this way.