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.

Validate the configuration and harden what a deployment creates

ed1812123cd9e9df0f34fdaf0d2511a340c2aaa6 · Keenan Nemetz · 13d ago · parent 13cff33f

Validate the configuration and harden what a deployment creates

Two ways an instance used to run in a state it should have refused.

The configuration was never checked. `dev_login` was guarded only by a loopback
listener, so a proxy that rewrites Host to 127.0.0.1 inherited a credential-free
session; open registration could be enabled on a plain-HTTP origin WebAuthn would
never accept; a public_url could carry a path or credentials; a size could be
negative. Config.Validate now runs before anything is opened and reports every
problem at once, and dev_login requires an explicit dev_only opt-in next to a
loopback listener with no public address. The per-request check no longer trusts
Host at all: it must name the configured listener, and a request carrying a
forwarding header gets no session.

The files were never checked either. directories were created 0755 and the audit
log 0644, and a file keeps the mode it was created with, so an upgraded instance
stayed exposed. internal/secure creates secrets at 0600 in directories at 0700,
tightens what an existing install left, keeps group access for a shared backup
group, and refuses to start when a mode cannot be changed. Every audit writer and
the account backup go through it. The service unit drops all capabilities,
sets UMask=0027, disables core dumps, hides other processes and devices, and
restricts address families; docs/operations.md now states the production
baseline.

forge/config/config.go +8−3

@@ -107,10 +107,14 @@ type Config struct {
107 107 // print a link to something it just created.
108 108 PublicURL string `toml:"public_url"`
109 109 // DevLogin is a development-only escape hatch: when set to an account name,
110 // a browser request from loopback is signed in as that account. It is refused
111 // unless http_addr is itself a loopback address, and the instance logs a
112 // warning at startup. Never enable it on a shared instance.
110 // a browser request from loopback is signed in as that account. It requires
111 // dev_only, a loopback http_addr, and no public_url or https_addr, and the
112 // instance logs a warning at startup. Never enable it on a shared instance.
113 113 DevLogin string `toml:"dev_login"`
114 // DevOnly acknowledges that this instance is a development instance. It is what
115 // makes dev_login an explicit decision rather than a setting somebody copied
116 // from an example: without it, dev_login is refused at startup.
117 DevOnly bool `toml:"dev_only"`
114 118
115 119 // Path is the file Load was asked to read. Loaded reports whether it found a
116 120 // non-empty file there; false means the built-in defaults are in use, which
@@ -278,6 +282,7 @@ ssh_addr = "127.0.0.1:2222"
278 282
279 283 # Development only: sign loopback browser requests in as this account. Refused
280 284 # unless http_addr is a loopback address. Never enable this on a shared instance.
285 # dev_only = true
281 286 # dev_login = "you"
282 287
283 288 # Let anyone create an account by registering a passkey. New accounts have no