Files
steve bb4ed3502d P5: OSS readiness — docs site, contributor onboarding, e2e harness
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.
2026-05-08 20:08:23 +01:00

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:

  1. 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.
  2. 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

  1. Acknowledge receipt within 3 working days.
  2. 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.
  3. Develop a fix on a private branch, test it, and prepare a release.
  4. 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.
  5. 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 restic directly 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_PROXY to the proxy's CIDR so request IPs aren't spoofable.
  • Back up RM_SECRET_KEY_FILE separately 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.