Severity: Low
Category: Hardening (server / deployment)
Affected files: src/server/config.ts, src/server/types.ts (AppConfig), src/server/index.ts (line 76), README.md, deploy/systemd/openhab-log-viewer.service. Line numbers refer to main @ 3ac64da.
Problem
app.listen(config.port, …) binds to all interfaces (0.0.0.0 / ::). The documented auth story for this app is "no built-in auth; put a reverse proxy in front when exposure matters". But a deployment that runs the reverse proxy on the same host cannot currently restrict the viewer to loopback — the unauthenticated API stays directly reachable on every interface, including ones the admin may not think about (a second NIC, a VPN interface, a container/VM bridge). The same applies to admins who simply want localhost-only access.
Suggested fix
src/server/config.ts: read a new env var BIND_ADDRESS. Default '0.0.0.0' to preserve current behavior exactly. Validation: trim; if empty after trim, use the default. No further validation needed — an unbindable address will fail loudly at listen() (see step 3). Add bindAddress: string to AppConfig in src/server/types.ts.
src/server/index.ts: pass it through and include it in the startup log line:
const server = app.listen(config.port, config.bindAddress, () => {
console.log(`OpenHab Log Viewer listening on ${config.bindAddress}:${config.port}`);
});
- Fail loudly on a bad address: attach an error handler so a typo'd
BIND_ADDRESS (EADDRNOTAVAIL) produces a clear fatal message instead of an unhandled 'error' event:
server.on('error', (error) => {
console.error('[startup] Failed to bind server:', error);
process.exit(1);
});
(With Restart=always in the systemd unit this will loop with RestartSec=5, which is acceptable and matches how an invalid log path behaves today; the log message makes the cause obvious.)
4. Docs: document BIND_ADDRESS in the README.md configuration section (default, purpose, example BIND_ADDRESS=127.0.0.1 for the same-host reverse-proxy setup) and add a commented line to deploy/systemd/openhab-log-viewer.service next to the other commented options:
# Uncomment to restrict the listener, e.g. when a reverse proxy runs on this host:
# Environment=BIND_ADDRESS=127.0.0.1
Acceptance criteria
- Default behavior unchanged: unset/empty
BIND_ADDRESS → binds as today, existing tests pass.
src/server/config.test.ts: BIND_ADDRESS=127.0.0.1 → config.bindAddress === '127.0.0.1'; unset → '0.0.0.0'; whitespace-only → '0.0.0.0'.
npm test and npm run typecheck pass.
Severity: Low
Category: Hardening (server / deployment)
Affected files:
src/server/config.ts,src/server/types.ts(AppConfig),src/server/index.ts(line 76),README.md,deploy/systemd/openhab-log-viewer.service. Line numbers refer tomain@3ac64da.Problem
app.listen(config.port, …)binds to all interfaces (0.0.0.0/::). The documented auth story for this app is "no built-in auth; put a reverse proxy in front when exposure matters". But a deployment that runs the reverse proxy on the same host cannot currently restrict the viewer to loopback — the unauthenticated API stays directly reachable on every interface, including ones the admin may not think about (a second NIC, a VPN interface, a container/VM bridge). The same applies to admins who simply want localhost-only access.Suggested fix
src/server/config.ts: read a new env varBIND_ADDRESS. Default'0.0.0.0'to preserve current behavior exactly. Validation: trim; if empty after trim, use the default. No further validation needed — an unbindable address will fail loudly atlisten()(see step 3). AddbindAddress: stringtoAppConfiginsrc/server/types.ts.src/server/index.ts: pass it through and include it in the startup log line:BIND_ADDRESS(EADDRNOTAVAIL) produces a clear fatal message instead of an unhandled'error'event:(With
Restart=alwaysin the systemd unit this will loop withRestartSec=5, which is acceptable and matches how an invalid log path behaves today; the log message makes the cause obvious.)4. Docs: document
BIND_ADDRESSin theREADME.mdconfiguration section (default, purpose, exampleBIND_ADDRESS=127.0.0.1for the same-host reverse-proxy setup) and add a commented line todeploy/systemd/openhab-log-viewer.servicenext to the other commented options:Acceptance criteria
BIND_ADDRESS→ binds as today, existing tests pass.src/server/config.test.ts:BIND_ADDRESS=127.0.0.1→config.bindAddress === '127.0.0.1'; unset →'0.0.0.0'; whitespace-only →'0.0.0.0'.npm testandnpm run typecheckpass.