From 7e2f656cf8af3bc2cca0797521d6f4e9663d9a82 Mon Sep 17 00:00:00 2001 From: Leszek Szpunar <13106764+leszekszpunar@users.noreply.github.com> Date: Fri, 30 Jan 2026 12:49:20 +0100 Subject: [PATCH] security(crypto): replace SHA-1 with SHA-256 in all hash operations SHA-1 is cryptographically broken and vulnerable to collision attacks. Replace all internal usages with SHA-256: - sandbox session key slugs (shared.ts) - sandbox config change detection (config-hash.ts) - tool call ID generation (tool-call-id.ts) - gateway lock file naming (gateway-lock.ts) All hashes are ephemeral (session-scoped slugs, lock filenames, tool IDs) so the algorithm change has no persistence impact. Fixes #2994 --- src/agents/sandbox/config-hash.ts | 2 +- src/agents/sandbox/shared.ts | 2 +- src/agents/tool-call-id.ts | 2 +- src/infra/gateway-lock.test.ts | 2 +- src/infra/gateway-lock.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/agents/sandbox/config-hash.ts b/src/agents/sandbox/config-hash.ts index 872bac4bc..c0e01e1c3 100644 --- a/src/agents/sandbox/config-hash.ts +++ b/src/agents/sandbox/config-hash.ts @@ -49,5 +49,5 @@ function primitiveToString(value: unknown): string { export function computeSandboxConfigHash(input: SandboxHashInput): string { const payload = normalizeForHash(input); const raw = JSON.stringify(payload); - return crypto.createHash("sha1").update(raw).digest("hex"); + return crypto.createHash("sha256").update(raw).digest("hex"); } diff --git a/src/agents/sandbox/shared.ts b/src/agents/sandbox/shared.ts index fe9a80bcd..1301548b3 100644 --- a/src/agents/sandbox/shared.ts +++ b/src/agents/sandbox/shared.ts @@ -7,7 +7,7 @@ import { resolveAgentIdFromSessionKey } from "../agent-scope.js"; export function slugifySessionKey(value: string) { const trimmed = value.trim() || "session"; - const hash = crypto.createHash("sha1").update(trimmed).digest("hex").slice(0, 8); + const hash = crypto.createHash("sha256").update(trimmed).digest("hex").slice(0, 8); const safe = trimmed .toLowerCase() .replace(/[^a-z0-9._-]+/g, "-") diff --git a/src/agents/tool-call-id.ts b/src/agents/tool-call-id.ts index 8b7e05417..a133c16e2 100644 --- a/src/agents/tool-call-id.ts +++ b/src/agents/tool-call-id.ts @@ -40,7 +40,7 @@ export function isValidCloudCodeAssistToolId(id: string, mode: ToolCallIdMode = } function shortHash(text: string, length = 8): string { - return createHash("sha1").update(text).digest("hex").slice(0, length); + return createHash("sha256").update(text).digest("hex").slice(0, length); } function makeUniqueToolId(params: { id: string; used: Set; mode: ToolCallIdMode }): string { diff --git a/src/infra/gateway-lock.test.ts b/src/infra/gateway-lock.test.ts index f40dd62b1..3d4b76c89 100644 --- a/src/infra/gateway-lock.test.ts +++ b/src/infra/gateway-lock.test.ts @@ -29,7 +29,7 @@ async function makeEnv() { function resolveLockPath(env: NodeJS.ProcessEnv) { const stateDir = resolveStateDir(env); const configPath = resolveConfigPath(env, stateDir); - const hash = createHash("sha1").update(configPath).digest("hex").slice(0, 8); + const hash = createHash("sha256").update(configPath).digest("hex").slice(0, 8); const lockDir = resolveGatewayLockDir(); return { lockPath: path.join(lockDir, `gateway.${hash}.lock`), configPath }; } diff --git a/src/infra/gateway-lock.ts b/src/infra/gateway-lock.ts index 6d707ff68..a3f3ba539 100644 --- a/src/infra/gateway-lock.ts +++ b/src/infra/gateway-lock.ts @@ -150,7 +150,7 @@ async function readLockPayload(lockPath: string): Promise { function resolveGatewayLockPath(env: NodeJS.ProcessEnv) { const stateDir = resolveStateDir(env); const configPath = resolveConfigPath(env, stateDir); - const hash = createHash("sha1").update(configPath).digest("hex").slice(0, 8); + const hash = createHash("sha256").update(configPath).digest("hex").slice(0, 8); const lockDir = resolveGatewayLockDir(); const lockPath = path.join(lockDir, `gateway.${hash}.lock`); return { lockPath, configPath };