| Version | Security updates |
|---|---|
v0.9.17 and later |
✅ Yes |
Earlier v0.9.x releases |
❌ No — please upgrade |
Please do NOT open a public GitHub issue for security bugs. Even describing an attack path in a public forum before a fix ships puts other users at risk.
Use GitHub's private vulnerability reporting: Report a vulnerability
This is the only intended channel — reports stay private to maintainers, and there is no e-mail thread to leak.
- Constat version (from the About section, or
GET /api/version) - Clear reproduction steps (command + request body + expected vs actual response is ideal)
- Impact assessment — what data/access can the attacker obtain? (Constat has Docker-socket access, so the blast radius for auth-bypass is higher than a typical API-only tool — please be specific.)
- Your disclosure timeline preference
- Acknowledgement within 72 hours of receipt (usually faster — solo maintainer, best-effort).
- Triage and severity assessment within 7 days. I'll confirm whether I accept the finding, classify severity, and propose a fix + disclosure timeline.
- Fix within 14 days for Critical/High findings. Medium/Low may take a release cycle.
- Coordinated disclosure — I'll ship a patched release first, then credit you in the CHANGELOG and this document (unless you prefer anonymity). Please do not publish details before the patch ships.
- Reporter credit in CHANGELOG + this document by default (anonymous on request).
- Honest acknowledgement when a report is valid — including in the CHANGELOG.
- Open to public discussion of a finding after the patch ships.
Constat is a local Docker management tool — it reads the Docker socket, lists containers, runs container-level commands (restart, update). This is significantly more privileged than a typical web app:
- Host assumption: You control the machine where Constat runs. Constat has effective root via the Docker socket.
- Network assumption: Port 7890 is not exposed directly to the internet. Use a reverse proxy with TLS if any external access is needed.
- File-system assumption:
/config/is writable only by the container UID (PUID:PGID). Other users on the same host should not have read access — Constat does not attempt to protect against a hostile local root.
- Authentication required by default (Forms mode, bcrypt cost 12). First-run setup wizard forces admin account creation — no default credentials.
- CSRF protection on all state-mutating endpoints (double-submit cookie pattern).
- Security headers:
X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy: same-origin. - SSRF guards on outbound HTTP (registry queries, Docker Hub / GHCR, webhook notifications) — blocklisted internal IP ranges + per-request DNS revalidation.
- Secret masking in all API responses — Discord webhooks, registry credentials, Gotify/Pushover tokens. Empty-on-unchanged-edit preserves stored secrets.
- Session persistence to disk (atomic write, survives container restart).
- File permissions:
/config/auth.jsonmode0600in dir0700./config/constat.confmode0600— contains Discord webhook URLs, Gotify token, Pushover user/app keys, and bot-name/server-label config./config/.docker/config.json(registry credentials) mode0600in dir0700. - X-Forwarded-For hardening: only trusted when the direct peer matches a configured Trusted Proxy. Rightmost-non-trusted algorithm.
- Env-var override for trust-boundary config (
TRUSTED_NETWORKS,TRUSTED_PROXIES) — pin at host level to defend against UI-takeover attackers. - Password re-confirmation on catastrophic ops (disabling auth). Local-bypass peers can't silently disable auth just by reaching the UI.
- Registry credentials plaintext on disk. Stored in Docker config format at
/config/.docker/config.json(mode 0600 in dir 0700). Same trust model as runningdocker loginon the host — if an attacker has filesystem access, they have the credentials. - Rate limiting on
/login. Delegated to the reverse proxy. - Account lockout. Same reasoning.
- Audit log of admin actions. The Docker event stream + reverse-proxy access logs cover this.
- TLS termination. Runs plain HTTP on port 7890. Use a reverse proxy for TLS.
Constat's security implementation is backed by an internal trap catalogue (T1–T66) — every finding from past code reviews is preserved with the mitigation pattern and the reason it was flagged. This is a living internal document (not published to this repo) covering the full hardening arc: auth primitives, middleware wiring, sensitive-data redaction, CSRF, security headers, race conditions, info leakage, log injection, supply-chain, and Docker-socket privilege-boundary concerns. Four full review rounds on Phase 1+2 + a delta review on env-var lock additions + a 5-agent parallel audit produced the current trap set. Requests for access to specific trap rationale can be made via the disclosure email above.
Current CI: go test -race ./... + govulncheck ./... run on every push and PR against main.
See CHANGELOG.md — entries flagged Security or explicitly reference trap IDs (T1–T66).