fix(SEC-ORCH-20): Bind orchestrator to 127.0.0.1 by default
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Change default bind address from 0.0.0.0 to 127.0.0.1 to prevent
the orchestrator API from being exposed on all network interfaces.
The bind address is now configurable via HOST or BIND_ADDRESS env
vars for Docker/production deployments that need 0.0.0.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-06 13:42:51 -06:00
parent c38271da3b
commit 25d2958fe4
3 changed files with 42 additions and 2 deletions

View File

@@ -54,6 +54,44 @@ describe("orchestratorConfig", () => {
}); });
}); });
describe("host binding", () => {
it("should default to 127.0.0.1 when no env vars are set", () => {
delete process.env.HOST;
delete process.env.BIND_ADDRESS;
const config = orchestratorConfig();
expect(config.host).toBe("127.0.0.1");
});
it("should use HOST env var when set", () => {
process.env.HOST = "0.0.0.0";
delete process.env.BIND_ADDRESS;
const config = orchestratorConfig();
expect(config.host).toBe("0.0.0.0");
});
it("should use BIND_ADDRESS env var when HOST is not set", () => {
delete process.env.HOST;
process.env.BIND_ADDRESS = "192.168.1.100";
const config = orchestratorConfig();
expect(config.host).toBe("192.168.1.100");
});
it("should prefer HOST over BIND_ADDRESS when both are set", () => {
process.env.HOST = "0.0.0.0";
process.env.BIND_ADDRESS = "192.168.1.100";
const config = orchestratorConfig();
expect(config.host).toBe("0.0.0.0");
});
});
describe("other config values", () => { describe("other config values", () => {
it("should use default port when ORCHESTRATOR_PORT is not set", () => { it("should use default port when ORCHESTRATOR_PORT is not set", () => {
delete process.env.ORCHESTRATOR_PORT; delete process.env.ORCHESTRATOR_PORT;

View File

@@ -1,6 +1,7 @@
import { registerAs } from "@nestjs/config"; import { registerAs } from "@nestjs/config";
export const orchestratorConfig = registerAs("orchestrator", () => ({ export const orchestratorConfig = registerAs("orchestrator", () => ({
host: process.env.HOST ?? process.env.BIND_ADDRESS ?? "127.0.0.1",
port: parseInt(process.env.ORCHESTRATOR_PORT ?? "3001", 10), port: parseInt(process.env.ORCHESTRATOR_PORT ?? "3001", 10),
valkey: { valkey: {
host: process.env.VALKEY_HOST ?? "localhost", host: process.env.VALKEY_HOST ?? "localhost",

View File

@@ -10,10 +10,11 @@ async function bootstrap() {
}); });
const port = process.env.ORCHESTRATOR_PORT ?? 3001; const port = process.env.ORCHESTRATOR_PORT ?? 3001;
const host = process.env.HOST ?? process.env.BIND_ADDRESS ?? "127.0.0.1";
await app.listen(Number(port), "0.0.0.0"); await app.listen(Number(port), host);
logger.log(`🚀 Orchestrator running on http://0.0.0.0:${String(port)}`); logger.log(`🚀 Orchestrator running on http://${host}:${String(port)}`);
} }
void bootstrap(); void bootstrap();