openclaw/src/agents/sandbox/shared.ts
Leszek Szpunar 7e2f656cf8 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
2026-01-30 12:49:20 +01:00

40 lines
1.5 KiB
TypeScript

import crypto from "node:crypto";
import path from "node:path";
import { normalizeAgentId } from "../../routing/session-key.js";
import { resolveUserPath } from "../../utils.js";
import { resolveAgentIdFromSessionKey } from "../agent-scope.js";
export function slugifySessionKey(value: string) {
const trimmed = value.trim() || "session";
const hash = crypto.createHash("sha256").update(trimmed).digest("hex").slice(0, 8);
const safe = trimmed
.toLowerCase()
.replace(/[^a-z0-9._-]+/g, "-")
.replace(/^-+|-+$/g, "");
const base = safe.slice(0, 32) || "session";
return `${base}-${hash}`;
}
export function resolveSandboxWorkspaceDir(root: string, sessionKey: string) {
const resolvedRoot = resolveUserPath(root);
const slug = slugifySessionKey(sessionKey);
return path.join(resolvedRoot, slug);
}
export function resolveSandboxScopeKey(scope: "session" | "agent" | "shared", sessionKey: string) {
const trimmed = sessionKey.trim() || "main";
if (scope === "shared") return "shared";
if (scope === "session") return trimmed;
const agentId = resolveAgentIdFromSessionKey(trimmed);
return `agent:${agentId}`;
}
export function resolveSandboxAgentId(scopeKey: string): string | undefined {
const trimmed = scopeKey.trim();
if (!trimmed || trimmed === "shared") return undefined;
const parts = trimmed.split(":").filter(Boolean);
if (parts[0] === "agent" && parts[1]) return normalizeAgentId(parts[1]);
return resolveAgentIdFromSessionKey(trimmed);
}