VIRP is a security-critical protocol. If you discover a vulnerability in the cryptographic verification path, chain integrity, HMAC signing, or trust tier enforcement:
Do NOT open a public issue.
Email: nhoward@thirdlevelit.com
Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact assessment
- Suggested fix (if you have one)
We will acknowledge receipt within 48 hours and provide a timeline for remediation.
The following are in scope for security reports:
- HMAC-SHA256 signing bypass or forgery
- Trust tier escalation (e.g., RED command executing as GREEN)
- Chain database tampering without detection
- O-Node socket authentication bypass
- Device credential exposure through the API layer
- Session handshake state machine violations
- Denial of service against the O-Node (known limitation — single-process architecture)
- Issues requiring physical access to the host machine
- Social engineering
The O-Node Unix domain socket is gated by SO_PEERCRED (Linux). VIRP
currently supports Linux only; the BSD getpeereid equivalent is not
implemented. Every accept() reads the connecting process's UID and
compares it against a startup-loaded allowlist:
VIRP_ALLOWED_UIDS— comma-separated UID list (e.g.VIRP_ALLOWED_UIDS=0,1001)- Prod builds also honor
socket_allowed_uidsin the JSON config - If neither is set, the allowlist defaults to the daemon's own effective UID — closed to every other local user
Rejected connections are closed immediately without reading any bytes
and produce a single REJECTED connection: peer uid=... log line.
The socket itself is created mode 0660 atomically via umask(0117) set
around bind() (with a belt-and-suspenders chmod(0660) after), so
there is no window in which a world-accessible node exists on disk.
VIRP defines two distinct paths that reach the O-Node. Their protections are not the same, and a protection that applies to one does not automatically apply to the other.
Local Unix domain socket — /run/virp/onode.sock (prod) or
/tmp/virp-onode.sock (dev). Protected by:
SO_PEERCREDpeer-UID allowlist (see previous section) — the kernel reports the caller's real UID, which is checked against the startup-loaded allowlist before any bytes are read.- Filesystem mode
0660with ownership restricted to the daemon's service user/group. - VIRP message-layer session handshake (
SESSION_HELLO/SESSION_HELLO_ACKwith nonces, followed by HKDF session-key derivation) on every fresh connection. - HMAC-SHA256 signing of every observation returned to the caller, using an O-Key the caller does not possess.
TCP path (CT 210 dashboard ↔ CT 211 O-Node, ports 9998/9999) — the
dashboard's virp-bridge.py listens on TCP 9998 locally on CT 210 and
opens a TCP connection to CT 211:9999, where a socat forwarder proxies
to the Unix socket. On this path:
SO_PEERCREDsees the local socat process's UID, not the remote dashboard's identity. It cannot distinguish authorized dashboard traffic from any other process on CT 211 that can reach the socat forwarder.- The VIRP message-layer session handshake and HMAC signing of observations still apply — observations returned across the TCP bridge are signed at collection time with the O-Key and are as verifiable as on the local path. An attacker who intercepts or injects on the TCP path cannot forge observations without the O-Key.
- The TCP path itself is not currently TLS-protected, and the
session handshake authenticates session establishment via nonce
exchange but does not cryptographically bind to a TCP endpoint
identity. Confidentiality, integrity of requests in flight, and
mutual authentication of the two containers currently rely on:
- W1 egress isolation (CT 210 can reach only allowlisted ports on CT 211),
- network segmentation between the two containers,
- the O-Key's secrecy on CT 211 (observations remain unforgeable even if the request channel is compromised).
Open work. TCP-path mutual authentication — either mTLS between the dashboard bridge and the socat endpoint, or request-side signing at the VIRP message layer — is not yet implemented and is tracked as follow-up hardening.
| Version | Supported |
|---|---|
| main branch | ✅ |
| Older commits | Best-effort |
Security researchers who report valid vulnerabilities will be credited in the CHANGELOG (unless they prefer anonymity).