diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a6043de95a..01e8c20d296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Docs: https://docs.openclaw.ai - Docs: fix FAQ typos and add documentation spellcheck automation with a custom codespell dictionary/ignore list, including CI coverage. (#22457) Thanks @vincentkoc. - Security/Unused Dependencies: add dead-code scans to CI via Knip/ts-prune/ts-unused-exports and report unused dependencies/exports in non-blocking checks. (#22468) Thanks @vincentkoc. +- Security/Agents: make owner-ID obfuscation use a dedicated HMAC secret from configuration (`ownerDisplaySecret`) and update hashing behavior so obfuscation is decoupled from gateway token handling for improved control. (#7343) Thanks @vincentkoc. +- Security/Infra: switch gateway lock and tool-call synthetic IDs from SHA-1 to SHA-256 with unchanged truncation length to strengthen hash basis while keeping deterministic behavior and lock key format. (#7343) Thanks @vincentkoc. - Security/Unused Dependencies: move `@larksuiteoapi/node-sdk` out of root `package.json` and keep it scoped to `extensions/feishu` where it is used. (#22471) Thanks @vincentkoc. - Security/Unused Dependencies: remove unused root dependency `signal-utils` from core manifest after confirming it was only used by extension-only paths. (#22471) Thanks @vincentkoc. - Security/Unused Dependencies: remove unused root devDependency `ollama` now that native Ollama support uses local HTTP transport code paths only. (#22471) Thanks @vincentkoc. diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index 0fd0b7a2272..e92207972eb 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -1,11 +1,11 @@ +import { createHmac, createHash } from "node:crypto"; import type { ReasoningLevel, ThinkLevel } from "../auto-reply/thinking.js"; -import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; import type { MemoryCitationsMode } from "../config/types.memory.js"; -import { listDeliverableMessageChannels } from "../utils/message-channel.js"; import type { ResolvedTimeFormat } from "./date-time.js"; import type { EmbeddedContextFile } from "./pi-embedded-helpers.js"; +import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; +import { listDeliverableMessageChannels } from "../utils/message-channel.js"; import { sanitizeForPromptLiteral } from "./sanitize-for-prompt.js"; -import { createHmac, createHash } from "node:crypto"; /** * Controls which hardcoded sections are included in the system prompt. @@ -80,7 +80,7 @@ function formatOwnerDisplayId(ownerId: string, ownerDisplaySecret?: string) { const digest = hasSecret ? createHmac("sha256", hasSecret).update(ownerId).digest("hex") : createHash("sha256").update(ownerId).digest("hex"); - return digest.slice(0, 16); + return digest.slice(0, 12); } function buildOwnerIdentityLine( diff --git a/src/agents/tool-call-id.ts b/src/agents/tool-call-id.ts index 00585be0693..fa28d6f0c8f 100644 --- a/src/agents/tool-call-id.ts +++ b/src/agents/tool-call-id.ts @@ -1,5 +1,5 @@ -import { createHash } from "node:crypto"; import type { AgentMessage } from "@mariozechner/pi-agent-core"; +import { createHash } from "node:crypto"; export type ToolCallIdMode = "strict" | "strict9"; @@ -94,7 +94,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/config/zod-schema.session.ts b/src/config/zod-schema.session.ts index 1b6e396b8f1..08fcafa2e87 100644 --- a/src/config/zod-schema.session.ts +++ b/src/config/zod-schema.session.ts @@ -3,7 +3,6 @@ import { parseByteSize } from "../cli/parse-bytes.js"; import { parseDurationMs } from "../cli/parse-duration.js"; import { ElevatedAllowFromSchema } from "./zod-schema.agent-runtime.js"; import { createAllowDenyChannelRulesSchema } from "./zod-schema.allowdeny.js"; -import { sensitive } from "./zod-schema.sensitive.js"; import { GroupChatSchema, InboundDebounceSchema, @@ -11,6 +10,7 @@ import { QueueSchema, TtsConfigSchema, } from "./zod-schema.core.js"; +import { sensitive } from "./zod-schema.sensitive.js"; const SessionResetConfigSchema = z .object({ diff --git a/src/infra/gateway-lock.test.ts b/src/infra/gateway-lock.test.ts index f64a03edea3..e7dd523709b 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 d6dbf2266a4..ccca44c4b58 100644 --- a/src/infra/gateway-lock.ts +++ b/src/infra/gateway-lock.ts @@ -156,7 +156,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 };