fix(SEC-ORCH-28+29): Add Valkey connection timeout + workItems MaxLength
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
SEC-ORCH-28: Add connectTimeout (5000ms default) and commandTimeout (3000ms default) to Valkey/Redis client to prevent indefinite connection hangs. Both are configurable via VALKEY_CONNECT_TIMEOUT_MS and VALKEY_COMMAND_TIMEOUT_MS environment variables. SEC-ORCH-29: Add @ArrayMaxSize(50) and @MaxLength(2000) to workItems in AgentContextDto to prevent memory exhaustion from unbounded input. Also adds @ArrayMaxSize(20) and @MaxLength(200) to skills array. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,11 +16,15 @@ const mockRedisInstance = {
|
||||
mget: vi.fn(),
|
||||
};
|
||||
|
||||
// Capture constructor arguments for verification
|
||||
let lastRedisConstructorArgs: unknown[] = [];
|
||||
|
||||
// Mock ioredis
|
||||
vi.mock("ioredis", () => {
|
||||
return {
|
||||
default: class {
|
||||
constructor() {
|
||||
constructor(...args: unknown[]) {
|
||||
lastRedisConstructorArgs = args;
|
||||
return mockRedisInstance;
|
||||
}
|
||||
},
|
||||
@@ -53,6 +57,25 @@ describe("ValkeyClient", () => {
|
||||
});
|
||||
|
||||
describe("Connection Management", () => {
|
||||
it("should pass default timeout options to Redis when not configured", () => {
|
||||
new ValkeyClient({ host: "localhost", port: 6379 });
|
||||
const options = lastRedisConstructorArgs[0] as Record<string, unknown>;
|
||||
expect(options.connectTimeout).toBe(5000);
|
||||
expect(options.commandTimeout).toBe(3000);
|
||||
});
|
||||
|
||||
it("should pass custom timeout options to Redis when configured", () => {
|
||||
new ValkeyClient({
|
||||
host: "localhost",
|
||||
port: 6379,
|
||||
connectTimeout: 10000,
|
||||
commandTimeout: 8000,
|
||||
});
|
||||
const options = lastRedisConstructorArgs[0] as Record<string, unknown>;
|
||||
expect(options.connectTimeout).toBe(10000);
|
||||
expect(options.commandTimeout).toBe(8000);
|
||||
});
|
||||
|
||||
it("should disconnect on close", async () => {
|
||||
mockRedis.quit.mockResolvedValue("OK");
|
||||
|
||||
|
||||
@@ -16,6 +16,10 @@ export interface ValkeyClientConfig {
|
||||
port: number;
|
||||
password?: string;
|
||||
db?: number;
|
||||
/** Connection timeout in milliseconds (default: 5000) */
|
||||
connectTimeout?: number;
|
||||
/** Command timeout in milliseconds (default: 3000) */
|
||||
commandTimeout?: number;
|
||||
logger?: {
|
||||
error: (message: string, error?: unknown) => void;
|
||||
};
|
||||
@@ -57,6 +61,8 @@ export class ValkeyClient {
|
||||
port: config.port,
|
||||
password: config.password,
|
||||
db: config.db,
|
||||
connectTimeout: config.connectTimeout ?? 5000,
|
||||
commandTimeout: config.commandTimeout ?? 3000,
|
||||
});
|
||||
this.logger = config.logger;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ export class ValkeyService implements OnModuleDestroy {
|
||||
const config: ValkeyClientConfig = {
|
||||
host: this.configService.get<string>("orchestrator.valkey.host", "localhost"),
|
||||
port: this.configService.get<number>("orchestrator.valkey.port", 6379),
|
||||
connectTimeout: this.configService.get<number>("orchestrator.valkey.connectTimeout", 5000),
|
||||
commandTimeout: this.configService.get<number>("orchestrator.valkey.commandTimeout", 3000),
|
||||
logger: {
|
||||
error: (message: string, error?: unknown) => {
|
||||
this.logger.error(message, error instanceof Error ? error.stack : String(error));
|
||||
|
||||
Reference in New Issue
Block a user