diff --git a/src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.ts b/src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.ts index a2260a93a..ccafb1454 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.ts @@ -31,8 +31,6 @@ function messageHasContentFromSDK(message: SDKMessage): boolean { } if (TOOL_TYPES.has(type)) return true - - return true } return false diff --git a/src/shared/opencode-message-dir.test.ts b/src/shared/opencode-message-dir.test.ts index bc5f449ad..521ddcdc3 100644 --- a/src/shared/opencode-message-dir.test.ts +++ b/src/shared/opencode-message-dir.test.ts @@ -71,6 +71,30 @@ describe("getMessageDir", () => { expect(result).toBe(sessionDir) }) + it("returns null for path traversal attempts with ..", () => { + //#given - sessionID containing path traversal + //#when + const result = getMessageDir("ses_../etc/passwd") + //#then + expect(result).toBe(null) + }) + + it("returns null for path traversal attempts with forward slash", () => { + //#given - sessionID containing forward slash + //#when + const result = getMessageDir("ses_foo/bar") + //#then + expect(result).toBe(null) + }) + + it("returns null for path traversal attempts with backslash", () => { + //#given - sessionID containing backslash + //#when + const result = getMessageDir("ses_foo\\bar") + //#then + expect(result).toBe(null) + }) + it("returns null when session not found anywhere", () => { //#given mkdirSync(join(TEST_MESSAGE_STORAGE, "subdir1"), { recursive: true }) diff --git a/src/shared/opencode-message-dir.ts b/src/shared/opencode-message-dir.ts index f330e84fa..c8d8e3b34 100644 --- a/src/shared/opencode-message-dir.ts +++ b/src/shared/opencode-message-dir.ts @@ -6,6 +6,7 @@ import { log } from "./logger" export function getMessageDir(sessionID: string): string | null { if (!sessionID.startsWith("ses_")) return null + if (/[/\\]|\.\./.test(sessionID)) return null if (isSqliteBackend()) return null if (!existsSync(MESSAGE_STORAGE)) return null