mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 12:17:26 +00:00
test: isolate local media regression fixtures to allowed roots (#22369)
* fix(tui): strip inbound metadata blocks from user text * chore: clean up metadata-strip format and changelog credit * chore: format tui metadata-strip tests * test(web): isolate local media fixture paths to allow-listed roots
This commit is contained in:
@@ -25,6 +25,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/Subagents: restore announce-chain delivery to agent injection, defer nested announce output until descendant follow-up content is ready, and prevent descendant deferrals from consuming announce retry budget so deep chains do not drop final completions. (#22223) Thanks @tyler6204.
|
||||
- Gateway/Auth: require `gateway.trustedProxies` to include a loopback proxy address when `auth.mode="trusted-proxy"` and `bind="loopback"`, preventing same-host proxy misconfiguration from silently blocking auth. (#22082, follow-up to #20097) thanks @mbelinky.
|
||||
- Security/OpenClawKit/UI: prevent injected inbound user context metadata blocks from leaking into chat history in TUI, webchat, and macOS surfaces by stripping all untrusted metadata prefixes at display boundaries. (#22142) Thanks @Mellowambience, @vincentkoc.
|
||||
- Security/OpenClawKit/UI: strip inbound metadata blocks from user messages in TUI rendering while preserving user-authored content. (#22345) Thanks @kansodata, @vincentkoc.
|
||||
- Security/OpenClawKit/UI: prevent inbound metadata leaks and reply-tag streaming artifacts in TUI rendering by stripping untrusted metadata prefixes at display boundaries. (#22346) Thanks @akramcodez, @vincentkoc.
|
||||
- Agents/System Prompt: label allowlisted senders as authorized senders to avoid implying ownership. Thanks @thewilloftheshadow.
|
||||
- Agents/Tool display: fix exec cwd suffix inference so `pushd ... && popd ... && <command>` does not keep stale `(in <dir>)` context in summaries. (#21925) thanks @Lukavyi.
|
||||
|
||||
@@ -16,6 +16,7 @@ vi.mock("./graph-upload.js", async () => {
|
||||
};
|
||||
});
|
||||
|
||||
import { resolvePreferredOpenClawTmpDir } from "../../../src/infra/tmp-openclaw-dir.js";
|
||||
import {
|
||||
type MSTeamsAdapter,
|
||||
renderReplyPayloadsToMessages,
|
||||
@@ -178,7 +179,7 @@ describe("msteams messenger", () => {
|
||||
});
|
||||
|
||||
it("preserves parsed mentions when appending OneDrive fallback file links", async () => {
|
||||
const tmpDir = await mkdtemp(path.join(os.tmpdir(), "msteams-mention-"));
|
||||
const tmpDir = await mkdtemp(path.join(resolvePreferredOpenClawTmpDir(), "msteams-mention-"));
|
||||
const localFile = path.join(tmpDir, "note.txt");
|
||||
await writeFile(localFile, "hello");
|
||||
|
||||
|
||||
@@ -95,6 +95,56 @@ describe("extractTextFromMessage", () => {
|
||||
|
||||
expect(text).toBe("[binary data omitted]");
|
||||
});
|
||||
|
||||
it("strips leading inbound metadata blocks for user messages", () => {
|
||||
const text = extractTextFromMessage({
|
||||
role: "user",
|
||||
content: `Conversation info (untrusted metadata):
|
||||
\`\`\`json
|
||||
{
|
||||
"message_id": "abc123"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
Sender (untrusted metadata):
|
||||
\`\`\`json
|
||||
{
|
||||
"label": "Someone"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
Actual user message`,
|
||||
});
|
||||
|
||||
expect(text).toBe("Actual user message");
|
||||
});
|
||||
|
||||
it("keeps metadata-like blocks for non-user messages", () => {
|
||||
const text = extractTextFromMessage({
|
||||
role: "assistant",
|
||||
content: `Conversation info (untrusted metadata):
|
||||
\`\`\`json
|
||||
{"message_id":"abc123"}
|
||||
\`\`\`
|
||||
|
||||
Assistant body`,
|
||||
});
|
||||
|
||||
expect(text).toContain("Conversation info (untrusted metadata):");
|
||||
expect(text).toContain("Assistant body");
|
||||
});
|
||||
|
||||
it("does not strip metadata-like blocks that are not a leading prefix", () => {
|
||||
const text = extractTextFromMessage({
|
||||
role: "user",
|
||||
content:
|
||||
'Hello world\nConversation info (untrusted metadata):\n```json\n{"message_id":"123"}\n```\n\nFollow-up',
|
||||
});
|
||||
|
||||
expect(text).toBe(
|
||||
'Hello world\nConversation info (untrusted metadata):\n```json\n{"message_id":"123"}\n```\n\nFollow-up',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("extractThinkingFromMessage", () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { formatRawAssistantErrorForUi } from "../agents/pi-embedded-helpers.js";
|
||||
import { stripInboundMetadataBlocks } from "../shared/chat-envelope.js";
|
||||
import { stripAnsi } from "../terminal/ansi.js";
|
||||
import { formatTokenCount } from "../utils/usage-format.js";
|
||||
|
||||
@@ -273,6 +274,9 @@ export function extractTextFromMessage(
|
||||
const record = message as Record<string, unknown>;
|
||||
const text = extractTextBlocks(record.content, opts);
|
||||
if (text) {
|
||||
if (record.role === "user") {
|
||||
return stripInboundMetadataBlocks(text);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { sendVoiceMessageDiscord } from "../discord/send.js";
|
||||
import * as ssrf from "../infra/net/ssrf.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
|
||||
import { optimizeImageToPng } from "../media/image-ops.js";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
import {
|
||||
@@ -50,7 +51,9 @@ async function createLargeTestJpeg(): Promise<{ buffer: Buffer; file: string }>
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-media-test-"));
|
||||
fixtureRoot = await fs.mkdtemp(
|
||||
path.join(resolvePreferredOpenClawTmpDir(), "openclaw-media-test-"),
|
||||
);
|
||||
largeJpegBuffer = await sharp({
|
||||
create: {
|
||||
width: 400,
|
||||
@@ -334,7 +337,9 @@ describe("local media root guard", () => {
|
||||
});
|
||||
|
||||
it("allows local paths under an explicit root", async () => {
|
||||
const result = await loadWebMedia(tinyPngFile, 1024 * 1024, { localRoots: [os.tmpdir()] });
|
||||
const result = await loadWebMedia(tinyPngFile, 1024 * 1024, {
|
||||
localRoots: [resolvePreferredOpenClawTmpDir()],
|
||||
});
|
||||
expect(result.kind).toBe("image");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user