All checks were successful
check / check (push) Successful in 3m1s
The plaintext listener bound `:PORT`, so it answered on every interface with no way to say otherwise. That published the admin UI and the unauthenticated receiver in cleartext beside whatever TLS proxy was in front of them, reachable from any host that could route to the machine. BIND_ADDRESS now selects the address, defaulting to 127.0.0.1. Loopback is the only default that does not silently expose that listener; reaching webhooker from another host becomes a deliberate act. A container must set BIND_ADDRESS=0.0.0.0, since a loopback bind inside a network namespace is unreachable even with -p, and the documented `docker run` does. Only IP address literals are accepted: hostnames, host:port and CIDR blocks abort startup naming the variable and the value, and a literal that is not an address of this host fails at listen and exits non-zero. The http.Server is now built in New rather than in the serving goroutine. Two goroutines reached that field with nothing ordering them — the serving goroutine assigning it, the fx stop hook calling Shutdown on it — which is a data race the race detector reports as soon as anything starts and stops the server, and a nil dereference if a stop arrived first. README gains a "Deployment behind a reverse proxy" section: a working nginx server block, and the five things that are silent when wrong — bind or firewall the app port, WEBHOOKER_ENVIRONMENT=prod, TRUSTED_PROXIES, Host as $http_host rather than $host, and keeping the proxy's access log because webhooker's own records only the proxy.
7.4 KiB
7.4 KiB