diff --git a/apps/orchestrator/src/valkey/valkey.service.spec.ts b/apps/orchestrator/src/valkey/valkey.service.spec.ts index 4f33c31..9950efe 100644 --- a/apps/orchestrator/src/valkey/valkey.service.spec.ts +++ b/apps/orchestrator/src/valkey/valkey.service.spec.ts @@ -82,6 +82,89 @@ describe("ValkeyService", () => { }); }); + describe("Security Warnings (SEC-ORCH-15)", () => { + it("should check NODE_ENV when VALKEY_PASSWORD not set in production", () => { + const configNoPassword = { + get: vi.fn((key: string, defaultValue?: unknown) => { + const config: Record = { + "orchestrator.valkey.host": "localhost", + "orchestrator.valkey.port": 6379, + NODE_ENV: "production", + }; + return config[key] ?? defaultValue; + }), + } as unknown as ConfigService; + + // Create a service to trigger the warning + const testService = new ValkeyService(configNoPassword); + expect(testService).toBeDefined(); + + // Verify NODE_ENV was checked (warning path was taken) + expect(configNoPassword.get).toHaveBeenCalledWith("NODE_ENV", "development"); + }); + + it("should check NODE_ENV when VALKEY_PASSWORD not set in development", () => { + const configNoPasswordDev = { + get: vi.fn((key: string, defaultValue?: unknown) => { + const config: Record = { + "orchestrator.valkey.host": "localhost", + "orchestrator.valkey.port": 6379, + NODE_ENV: "development", + }; + return config[key] ?? defaultValue; + }), + } as unknown as ConfigService; + + const testService = new ValkeyService(configNoPasswordDev); + expect(testService).toBeDefined(); + + // Verify NODE_ENV was checked (warning path was taken) + expect(configNoPasswordDev.get).toHaveBeenCalledWith("NODE_ENV", "development"); + }); + + it("should not check NODE_ENV when VALKEY_PASSWORD is configured", () => { + const configWithPassword = { + get: vi.fn((key: string, defaultValue?: unknown) => { + const config: Record = { + "orchestrator.valkey.host": "localhost", + "orchestrator.valkey.port": 6379, + "orchestrator.valkey.password": "secure-password", + NODE_ENV: "production", + }; + return config[key] ?? defaultValue; + }), + } as unknown as ConfigService; + + const testService = new ValkeyService(configWithPassword); + expect(testService).toBeDefined(); + + // NODE_ENV should NOT be checked when password is set (warning path not taken) + expect(configWithPassword.get).not.toHaveBeenCalledWith("NODE_ENV", "development"); + }); + + it("should default to development environment when NODE_ENV not set", () => { + const configNoEnv = { + get: vi.fn((key: string, defaultValue?: unknown) => { + const config: Record = { + "orchestrator.valkey.host": "localhost", + "orchestrator.valkey.port": 6379, + }; + // Return default value for NODE_ENV (simulating undefined env var) + if (key === "NODE_ENV") { + return defaultValue; + } + return config[key] ?? defaultValue; + }), + } as unknown as ConfigService; + + const testService = new ValkeyService(configNoEnv); + expect(testService).toBeDefined(); + + // Should have checked NODE_ENV with default "development" + expect(configNoEnv.get).toHaveBeenCalledWith("NODE_ENV", "development"); + }); + }); + describe("Lifecycle", () => { it("should disconnect on module destroy", async () => { mockClient.disconnect.mockResolvedValue(undefined); diff --git a/apps/orchestrator/src/valkey/valkey.service.ts b/apps/orchestrator/src/valkey/valkey.service.ts index 8121b6e..45fdfa8 100644 --- a/apps/orchestrator/src/valkey/valkey.service.ts +++ b/apps/orchestrator/src/valkey/valkey.service.ts @@ -33,6 +33,23 @@ export class ValkeyService implements OnModuleDestroy { const password = this.configService.get("orchestrator.valkey.password"); if (password) { config.password = password; + } else { + // SEC-ORCH-15: Warn when Valkey password is not configured + const nodeEnv = this.configService.get("NODE_ENV", "development"); + const isProduction = nodeEnv === "production"; + + if (isProduction) { + this.logger.warn( + "SECURITY WARNING: VALKEY_PASSWORD is not configured in production environment. " + + "Valkey connections without authentication are insecure. " + + "Set VALKEY_PASSWORD environment variable to secure your Valkey instance." + ); + } else { + this.logger.warn( + "VALKEY_PASSWORD is not configured. " + + "Consider setting VALKEY_PASSWORD for secure Valkey connections." + ); + } } this.client = new ValkeyClient(config);