Security

Security policies and vulnerability reporting for PatchPanel.

Table of contents

  1. TOC

Loading supported versions...

Security Policy

Reporting a Vulnerability

Please do not report security vulnerabilities through public GitHub issues.

If you discover a security vulnerability in PatchPanel, please report it through a private channel:

Preferred Method: Security Advisory

  1. Go to the GitHub Security Advisory page
  2. Click “Report a vulnerability”
  3. Fill out the advisory form with detailed information
  4. Submit the advisory

What to include

  • Description of the vulnerability
  • Steps to reproduce the issue
  • Potential impact of the vulnerability
  • Affected versions (if known)
  • Suggested fix (if you have one)
  • Your contact information for follow-up questions

Response Process

Maintained as a side-project with limited resources. Realistic timeline:

  • Initial response: 48–72 hours
  • Assessment: within 1 week
  • Resolution: typically 1–4 weeks depending on severity
  • Disclosure: coordinated, after a fix is available

Severity levels

  • Critical: RCE, privilege escalation. Immediate attention.
  • High: authentication bypass, key disclosure, data exfiltration. Days.
  • Medium: DoS, information disclosure. Standard timeline.
  • Low: minor information leaks. Lower priority.

High-risk surface areas

PatchPanel renders configuration for HAProxy — a TLS-terminating reverse proxy that frequently sits on a public IP — and reloads it via HAProxy’s master control socket. The blast radius of a PatchPanel vulnerability is the same as HAProxy’s blast radius. Special attention to:

  • HAProxy config injection — any path that lets unprivileged input land in the rendered haproxy.cfg without escaping (ACL values, header names, regex bodies, hostnames, server addresses)
  • Master CLI socket access — unauthorized reloads, server-state changes, or stick-table mutations via /run/haproxy-master.sock
  • Certificate / key handling — path traversal in BYO cert / trusted CA / CRL uploads; private key disclosure via the cfg-render endpoint or audit log
  • API key authentication — bcrypt-bypass, expired-key acceptance, permission-scope confusion
  • ACME challenge endpoints — path traversal in /.well-known/, spoofed validation responses
  • Command execution — PatchPanel shells out to certbot, haproxy -c, openssl, and the OS toolchain. Argument-injection surface lives there
  • State document validation — Zod-schema bypass that lets a malformed state through validation but crashes haproxy -c

Security posture by deployment surface

PatchPanel runs in two modes. The threat model differs.

Home Assistant add-on mode

The PatchPanel HTTP server speaks plain HTTP on a Docker-internal port and is reached only through the supervisor’s ingress proxy. TLS, public exposure, authentication, and access control are HA’s responsibility. The add-on:

  • Trusts the supervisor proxy IP via app.set('trust proxy', ...)
  • Reads X-Ingress-Path for asset URL prefixing
  • Reads X-Remote-User-* for audit-log attribution
  • Runs no local authentication, no session cookies, no CSRF middleware, no first-run wizard

Misconfiguring trust proxy or exposing the add-on’s internal port outside the supervisor breaks the security model.

Standalone Debian package mode

PatchPanel terminates its own TLS and runs its own auth. The intended hardening (some implemented today, some on the roadmap):

AreaImplementationStatus
TLS bootstrapSelf-signed cert generated via openssl req -x509 -nodes -days 365 -newkey rsa:2048Planned
TLS hardeningminVersion: TLSv1.2, maxVersion: TLSv1.3, ECDHE-only ciphers, honorCipherOrderPlanned
HSTS / CSP / framehelmet with CSP, HSTS (max-age + includeSubDomains + preload), X-Frame-Options DENYPlanned
Session authexpress-session + better-sqlite3 store, httpOnly + Secure + SameSite=Lax cookiePlanned
API key authbcrypt cost 12, per-key permission scopes, optional ≤1-year expiry, 8-char previewPlanned
Retrievable keysOptional AES-256-CBC encrypted full-key column (off by default)Planned
Password hashingbcrypt cost 12 for the local adminPlanned
CSRFlusca.csrf() gated to cookie-authenticated routes (skipped for Bearer + GET + SSE)Planned
CORScors package with whitelist origin array, credentials: truePlanned
Rate limitingexpress-rate-limit tiered: auth-strict, write, read-permissivePlanned
Input validationzod schemas at every API entry point + state-document schemaPartial
First-run gateSetup-only mode until /etc/patchpanel/setup.token is consumed; timing-safe comparePlanned
Audit logEvery state mutation persisted to audit.sqlite with actor + outcomeImplemented
HAProxy validationhaproxy -c against rendered cfg before atomic swapImplemented
Path traversalAll cert / CA / CRL paths resolved + bounded to dedicated directoriesImplemented

“Partial” for input validation = the HAProxy state document is fully Zod-validated today; the rest of the API surface validates ad-hoc.

The “Planned” rows correspond to roadmap items tracked in GitHub Issues under the security label. Until they land, run standalone PatchPanel behind a trusted network or another reverse proxy that does TLS / auth for you.

Hardening recommendations for operators

  • Keep PatchPanel updated. Subscribe to releases.
  • Run on the latest LTS Node.js — current target is Node 22+.
  • Use a real (Let’s Encrypt) cert for the management UI itself, not the self-signed bootstrap.
  • Restrict network access to the management port. Even with auth, the smaller the exposure the better.
  • Rotate API keys at least annually; set the shortest practical expiry.
  • Grant the narrowest permissions an integration needs. A read-only key is harmless if leaked; a haproxy-control key is not.
  • Watch the audit log for unexpected key usage.

Hall of fame

Contributors who responsibly report security vulnerabilities will be acknowledged here (with their permission):

  • No vulnerabilities reported yet.

Updates to this policy

This security policy may be updated as the project evolves. Check back periodically.