From cc0e215fa414d77c2ef7de3997eb3243b51444dc Mon Sep 17 00:00:00 2001 From: krissding Date: Thu, 16 Jul 2026 13:42:03 +0800 Subject: [PATCH] fix(sessions): stop leaking file path as prompt content on read failure (#108546) * fix(sessions): stop leaking file path as prompt content on read failure When readFileSync fails for a valid file path, resolvePromptInput returns the raw path string as prompt content instead of undefined. This injects filesystem paths into the LLM context. The existing console.error warning still fires; the caller already handles undefined returns correctly. Co-Authored-By: Claude Sonnet 4.6 * test: cover unreadable prompt paths * test: use tracked resource loader temp dirs --------- Co-authored-by: Claude Sonnet 4.6 Co-authored-by: Peter Steinberger Co-authored-by: Peter Steinberger (cherry picked from commit c9248192926ac164fe4a91af3fe72555a7512c67) --- src/agents/sessions/resource-loader.test.ts | 52 +++++++++++++++------ src/agents/sessions/resource-loader.ts | 2 +- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/agents/sessions/resource-loader.test.ts b/src/agents/sessions/resource-loader.test.ts index 47bec1f92a41..9407b11ec0e1 100644 --- a/src/agents/sessions/resource-loader.test.ts +++ b/src/agents/sessions/resource-loader.test.ts @@ -1,16 +1,15 @@ // Resource loader tests cover compatibility wiring for SDK prompt transform // aliases. -import { mkdtempSync, rmSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; -import { describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { useAutoCleanupTempDirTracker } from "../../../test/helpers/temp-dir.js"; import { DefaultResourceLoader } from "./resource-loader.js"; +const tempDirs = useAutoCleanupTempDirTracker(afterEach); + describe("DefaultResourceLoader", () => { - it("keeps deprecated SDK prompt override aliases wired to prompt transforms", async () => { - // These aliases are deprecated but shipped SDK surface, so they still map - // through the same transform path as the current options. - const root = mkdtempSync(join(tmpdir(), "openclaw-resource-loader-")); + it("does not use unreadable prompt file paths as prompt content", async () => { + const root = tempDirs.make("openclaw-resource-loader-"); + const consoleError = vi.spyOn(console, "error").mockImplementation(() => {}); try { const loader = new DefaultResourceLoader({ cwd: root, @@ -20,18 +19,41 @@ describe("DefaultResourceLoader", () => { noPromptTemplates: true, noThemes: true, noContextFiles: true, - systemPrompt: "base", - appendSystemPrompt: ["tail"], - systemPromptOverride: (base) => `${base ?? ""} legacy`, - appendSystemPromptOverride: (base) => [...base, "legacy"], + systemPrompt: root, + appendSystemPrompt: [root], }); await loader.reload(); - expect(loader.getSystemPrompt()).toBe("base legacy"); - expect(loader.getAppendSystemPrompt()).toEqual(["tail", "legacy"]); + expect(loader.getSystemPrompt()).toBeUndefined(); + expect(loader.getAppendSystemPrompt()).toEqual([]); + expect(consoleError).toHaveBeenCalledTimes(2); } finally { - rmSync(root, { force: true, recursive: true }); + consoleError.mockRestore(); } }); + + it("keeps deprecated SDK prompt override aliases wired to prompt transforms", async () => { + // These aliases are deprecated but shipped SDK surface, so they still map + // through the same transform path as the current options. + const root = tempDirs.make("openclaw-resource-loader-"); + const loader = new DefaultResourceLoader({ + cwd: root, + agentDir: root, + noExtensions: true, + noSkills: true, + noPromptTemplates: true, + noThemes: true, + noContextFiles: true, + systemPrompt: "base", + appendSystemPrompt: ["tail"], + systemPromptOverride: (base) => `${base ?? ""} legacy`, + appendSystemPromptOverride: (base) => [...base, "legacy"], + }); + + await loader.reload(); + + expect(loader.getSystemPrompt()).toBe("base legacy"); + expect(loader.getAppendSystemPrompt()).toEqual(["tail", "legacy"]); + }); }); diff --git a/src/agents/sessions/resource-loader.ts b/src/agents/sessions/resource-loader.ts index 5c2a45d53bc4..c31aa5e9290e 100644 --- a/src/agents/sessions/resource-loader.ts +++ b/src/agents/sessions/resource-loader.ts @@ -64,7 +64,7 @@ function resolvePromptInput(input: string | undefined, description: string): str console.error( chalk.yellow(`Warning: Could not read ${description} file ${input}: ${String(error)}`), ); - return input; + return undefined; } }