Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

#1

Production security hardening tracking issue

closed · opened by keenan 13d ago

keenan opened this 13d ago

Closed 2026-10-30: every P0 and P1 item shipped, and the P2 work this pointed at lives in #14.

Goal: make Vole safe to expose as a production forge. Close all P0 and P1 items before public deployment; P2 can follow after launch.

Threat model

  • Trusted: host OS, instance admins, runner operators, git, the OCI runtime.
  • Untrusted: anonymous web clients, repository content, contributors, workflows, site content, LFS/artifact bytes, invite links, and CI job containers.
  • Semi-trusted: maintainers, who can write metadata and approve changes.
  • Highest-risk boundary: a CI runner executes arbitrary repository code.

P0 — delivered before any public deployment

Item Issue Landed in
Go toolchain update and vulnerability scanning #2 #16
Bound and stream untrusted read-path objects #3 #47
Git HTTP and HTTP server limits #4 #48
SSH availability and host-key handling #5 #53
Audit log trust #6 #52
Configuration validation and dev_login guard #7 #49
Deployment file modes and systemd hardening #8 #49

P1 — delivered before production traffic

Item Issue Landed in
Auth, session, and invite-token hardening #9 #55
ACL races and approval/runner authorization durability #10 #54
CI runner trust boundary #11 #56, #57
Web transport, URL generation, and CSP #12 #58
Quotas and abuse controls #13 #59

What holds the line from here

The properties this issue was written to establish are now enforced by things that run, not by a checklist someone has to remember:

  • Every push, in .vole/workflows/verify.yaml: gofmt, go vet, go build, govulncheck pinned at v1.9.0 so a newly reachable vulnerability fails the push, a package build, the markdown links, and go test -race.
  • Every tag, in .vole/workflows/release.yaml: go vet and go test, govulncheck before anything is built, a reproducible package build, and SHA256SUMS over every attached file.
  • The settings, in Operations § Production baseline: the addresses, limits, and defaults that matter on the day an instance is exposed, each pointing at the section that explains it.

Last full check on this line of main: vole workflow run verify on 2026-10-30, all steps passing, 0 reachable vulnerabilities, every package green under -race.

What this issue no longer carries

Two lines of the old definition of done were evidence rather than hardening: a staging soak showing bounded memory, file descriptors, and process counts (#102), and the incident-response half of the deployment runbook (#105). docs/operations.md already covers TLS, the firewall, backups, and shipping the audit log; the incident-response section did not exist.

Both are P2, both belong to #14, and neither was a P0 or P1 fix, so neither holds this issue open.

P2 post-launch work: #14.

Comments (4)

keenan 13d ago

Child issues filed:

P0 — before public deployment

P1 — before production traffic

P2 — post-launch

Suggested order: start with the P0 toolchain, read-path, and Git HTTP items; then audit/config/deployment; then auth and ACL races; then the CI runner boundary and quotas.

keenan 13d ago

One unrelated bug was found while filing these issues and is tracked separately:

Workaround: use VOLE_CONFIG=/path/to/vole.toml until it is fixed.

keenan 10d ago

Status check before breaking this down further: every child issue in the plan below is closed, and each was closed by a merged change request.

  • #2 toolchain and vulnerability scanning — merged
  • #3 read-path bounds — merged
  • #4 Git HTTP and server limits — merged
  • #5 SSH availability and host keys — merged
  • #6 audit log trust — merged
  • #7 configuration and dev_login — merged
  • #8 deployment file modes and service unit — merged
  • #9 auth, sessions, and invite tokens — merged
  • #10 ACL races and approval durability — merged
  • #11 CI runner trust boundary — merged
  • #12 web transport, URL generation, and CSP — merged
  • #13 quotas and abuse controls — merged

So this issue is not large any more; the checklist above is stale, and it is stale in the other direction too — the - [ ] boxes were never ticked.

Of the five definition-of-done lines, three are evidenced by the workflows in the repository: govulncheck runs in verify and again on a tag, go vet and go test -race run in verify, and the fixes that landed carried regression tests. Two have nothing behind them:

  • Staging soak and load tests showing bounded memory, file descriptors, and process counts. There is no way to produce those numbers today. Tracked as #99 (harness), #100 and #101 (scenarios), and #102 (the soak itself, which is the line this issue asks for).
  • The deployment runbook’s incident response part. docs/operations.md covers TLS, the firewall, backups, and shipping the audit log off the host. It says nothing about what to do after a compromise. Tracked as #105, with #104 as the restore drill that keeps the backup half honest.

Those four issues are also the last of #14, so the two tracking issues now share their tail rather than duplicating it.

Proposal: keep this issue open only for #102 and #105, then close it. If that is right, the body should be rewritten to match — the P0 and P1 checklists ticked, the P2 line pointing at #14, and the definition of done reduced to those two links. I have not edited the body; say the word and I will.

keenan 10d ago

Closing on evidence.

vole workflow run verify in the pinned image on main (2026-10-30), all steps: gofmt clean, go vet and go build clean, govulncheck v1.9.0 with 0 reachable vulnerabilities, deb and rpm built, markdown links clean, go test -race -count=1 ./... green for every package. The body now lists what shipped and where, and what enforces it from here.

This goes further than the proposal in my previous comment, which kept the issue open for #102 and #105. That was the wrong call: this issue’s own goal is P0 and P1 before deployment, both are P2 evidence-gathering rather than fixes, and #14 already owns P2 — so keeping it open for them was the overlap, not the fix. Both remain in #14, unassigned to this issue.

Body rewritten as a record rather than a checklist: the stale - [ ] boxes are gone, each item links the issue that delivered it and the change request that landed it.