P5-01 — Documentation site under docs/book/ rendered with mdBook
(downloaded via Makefile, same static-binary pattern as Tailwind).
Structured chapters: getting started, concepts, operations,
security, reference. `make docs` / `make docs-watch`. Generated
output gitignored.
P5-02 — CONTRIBUTING.md rewritten from placeholder to a full
guide. CODE_OF_CONDUCT.md adapted from Contributor Covenant for a
single-maintainer project. .gitea/issue_template/{bug,feature}.md
and PULL_REQUEST_TEMPLATE.md.
P5-04 — Six README screenshots captured live from a fresh server
bootstrap (login, empty dashboard, add-host, alerts, settings,
audit log). README rewritten to centre the screenshot grid and
link out to the docs site.
P5-05 — SECURITY.md with disclosure policy (3-day ack, 30-day
default window), scope in/out, threat-model summary, operator
hardening checklist. Mirrored as a docs-site chapter.
P5-06 — End-to-end test harness. e2e/compose.e2e.yml brings up
server + sibling Linux agent (alpine + restic) + restic/rest-server.
Agent uses announce-and-approve so Playwright can drive the full
operator flow: bootstrap → login → accept pending → backup →
verify terminal status. Second spec scrapes /metrics to assert
the P6-04 endpoint surface. .gitea/workflows/e2e.yml runs on every
PR; local how-to in docs/e2e.md.
5.5 KiB
Security policy
restic-manager handles credentials that grant access to backup repositories — losing them means an attacker can read or destroy a fleet's backups. We take security reports seriously even at this project's small scale.
Supported versions
Pre-1.0, only the latest tagged release on main is supported.
Backporting fixes to older tags is not currently offered.
| Version | Supported |
|---|---|
main HEAD |
Yes |
| Latest released tag | Yes |
| Anything older | No |
Reporting a vulnerability
Please don't open a public issue for security problems.
Instead, use one of these private channels:
- Gitea private message to the repository owner. The
instance is at https://gitea.dcglab.co.uk and the owner's
profile (
steve) has direct-message contact set up. - Email to the address on the maintainer's Gitea profile.
Use a subject like
[SECURITY] restic-manager: <one-line summary>so it doesn't get lost. PGP optional — if you want to encrypt, ask for a key first.
If you don't get an acknowledgement within 3 working days, please escalate through the other channel — solo maintainers do miss things, and the goal here is to fix the problem, not to preserve protocol.
What to include
- A description of the issue and the impact (what does an attacker gain? confidentiality, integrity, availability?).
- Affected component (server, agent, install script, docs).
- Affected version (
restic-manager-server --version). - Reproduction steps if you have them. A working PoC is welcome but not required — a credible threat model is enough.
- Whether you intend to publish a writeup, and any timing preferences.
What we'll do
- Acknowledge receipt within 3 working days.
- Confirm or refute the issue, and agree a rough severity (CVSS or just "this is bad / this isn't"). Asking clarifying questions is normal at this stage — please don't read it as foot-dragging.
- Develop a fix on a private branch, test it, and prepare a release.
- Coordinate disclosure timing with you. The default is 30 days from confirmed report to public disclosure, with a patched release published before the disclosure date. Faster if a workable PoC is already circulating; slower only by mutual agreement.
- Credit the reporter in the release notes (or omit the credit if you'd rather stay anonymous — your choice).
Scope
In scope:
- The server binary (
cmd/server) and any HTTP, WebSocket, or CLI surface it exposes. - The agent binary (
cmd/agent) and the way it consumes commands from the server. - The install scripts (
deploy/install/install.sh,install.ps1) and the systemd unit shipped with them. - The docker-compose reference deployment and the docker image we publish.
- Any cryptographic primitive choice or implementation detail (AEAD, token hashing, session handling, OIDC handshake).
- Documentation that, if followed, leads operators into an insecure configuration.
Out of scope (not because they aren't real problems, just not ones this report channel can act on):
- Vulnerabilities in restic itself — report those upstream at https://github.com/restic/restic.
- Vulnerabilities in third-party dependencies that haven't yet been patched upstream — report upstream first.
- Issues that require pre-authenticated admin access on the control plane (admins can already do everything; that's not a privilege escalation, that's the design).
- DoS via resource exhaustion on a deployment without the
recommended reverse proxy / rate limiting in front (see
docs/reverse-proxy.md). - Social-engineering scenarios that don't have a technical hook into the project's own surfaces.
Threat model summary
For context (longer version in spec.md §11):
- The server is HTTP-only; TLS termination, ACME, HSTS, and edge rate-limiting are the reverse proxy's job.
- Credentials are encrypted at rest with an AEAD key loaded from
RM_SECRET_KEY_FILE. The same key encrypts agent secrets that travel to the agent over the WS channel. - Agents authenticate with bearer tokens issued at enrolment and hashed at rest. Compromise of the server DB does not leak bearer tokens in plaintext, but does leak the hashes (which is enough to log in as the agent until the operator revokes — see NS-01 / NS-02 for the revoke + regenerate flows).
- The control plane intentionally never touches backup bytes —
the agent runs
resticdirectly against the repo. A compromised control plane can dispatch new jobs but cannot exfiltrate snapshot contents in-band. - Append-only credentials are first-class. Forget/prune jobs use a separate, admin-marked credential that the server only pushes for the duration of a maintenance dispatch.
Hardening checklist for operators
- Run behind a TLS-terminating reverse proxy (Caddy/nginx/Traefik).
- Set
RM_TRUSTED_PROXYto the proxy's CIDR so request IPs aren't spoofable. - Back up
RM_SECRET_KEY_FILEseparately from the database. Without it the encrypted creds are unrecoverable. - Use append-only credentials for the everyday backup path; only the optional admin credential should have write/forget/prune power.
- Disable users (don't delete) when staff change roles — bearer tokens stay valid until rotated.
- Watch the alert and audit-log views during enrolment of new hosts.
Thanks for helping keep restic-manager users safe.