Security fixes are provided for the latest release on the main branch.
Please report security issues privately via GitHub Security Advisories on this repository, or open a minimal issue without posting exploit details publicly.
- Set strong, unique values for
ADMIN_PASSWORDandSESSION_SECRETin production. - Prefer a bcrypt hash for
ADMIN_PASSWORD(npm run hash-password -- "your-password"). - Set
COOKIE_SECURE=truewhen serving the dashboard over HTTPS. - Set
SESSION_MAX_AGE_DAYSto control how long sign-in sessions remain valid (default: 7). - Enable Dashboard requires sign-in in admin settings when the instance is reachable beyond trusted networks.
- Enable Public API (v1) only when you need programmatic access from other tools; store the API key like a password and rotate it after exposure.
- Do not commit
.envfiles or database backups with widget credentials. - Mount the Docker socket only via a restricted proxy, not directly.
- Grant widget API tokens the minimum permissions required.
- Keep the instance behind a firewall or reverse proxy with authentication if exposed beyond your LAN.
- Dashboard (browser) — Optional sign-in via Dashboard requires sign-in. When enabled, the UI and internal read APIs (
/api/dashboard,/api/settings,/api/health,/api/widgets, …) require a valid admin session cookie or a valid Public API key (Authorization: Bearer …/X-API-Key) when Public API v1 is enabled. - Public API v1 — Separate, opt-in REST API at
/api/v1/*. Disabled by default (returns 404). When enabled, requiresAuthorization: Bearer <key>orX-API-Key. Keys are 256-bit random values, encrypted at rest, compared withtimingSafeEqual. Failed auth attempts are rate-limited per IP.
If Dashboard requires sign-in is off, anyone who can reach the instance can read the same data the dashboard UI shows: service names, URLs, LAN URLs, health status, and widget hover data. Widget credentials are never included in API responses unless you are signed in as admin.
This is intentional for LAN homelab dashboards. For internet-facing deployments, enable dashboard sign-in.
- All write operations (admin CRUD, settings changes, backups) require an admin session (
requireAuth()). - Widget credentials are stripped from
/api/servicesunless signed in. - The encrypted public API key is never returned in settings API responses (only
public_api_key_configured: true). - Public API v1 serializers never export widget credentials.
HTTPS reverse proxy → Dashboard with sign-in enabled → Public API v1 only if needed
Environment: strong SESSION_SECRET, bcrypt ADMIN_PASSWORD, COOKIE_SECURE=true.
Without production env vars, the app falls back to development defaults (ADMIN_PASSWORD=admin, dev session secret). These must never be used on a public-facing deployment.