mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:50:43 +00:00
test: move chat image safety to direct render
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { mountApp, registerAppMountHooks } from "../test-helpers/app-mount.ts";
|
||||
|
||||
registerAppMountHooks();
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
function renderAssistantImage(url: string) {
|
||||
return {
|
||||
role: "assistant",
|
||||
content: [{ type: "image_url", image_url: { url } }],
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
describe("chat image open safety", () => {
|
||||
it("opens only safe image URLs in a hardened new tab", async () => {
|
||||
const app = mountApp("/chat");
|
||||
await app.updateComplete;
|
||||
|
||||
const openSpy = vi.spyOn(window, "open").mockReturnValue(null);
|
||||
|
||||
app.chatMessages = [renderAssistantImage("https://example.com/cat.png")];
|
||||
await app.updateComplete;
|
||||
|
||||
let image = app.querySelector<HTMLImageElement>(".chat-message-image");
|
||||
expect(image).not.toBeNull();
|
||||
image?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(openSpy).toHaveBeenCalledTimes(1);
|
||||
expect(openSpy).toHaveBeenCalledWith(
|
||||
"https://example.com/cat.png",
|
||||
"_blank",
|
||||
"noopener,noreferrer",
|
||||
);
|
||||
|
||||
openSpy.mockClear();
|
||||
app.chatMessages = [renderAssistantImage("javascript:alert(1)")];
|
||||
await app.updateComplete;
|
||||
|
||||
image = app.querySelector<HTMLImageElement>(".chat-message-image");
|
||||
expect(image).not.toBeNull();
|
||||
image?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(openSpy).not.toHaveBeenCalled();
|
||||
|
||||
openSpy.mockClear();
|
||||
app.chatMessages = [
|
||||
renderAssistantImage("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' />"),
|
||||
];
|
||||
await app.updateComplete;
|
||||
|
||||
image = app.querySelector<HTMLImageElement>(".chat-message-image");
|
||||
expect(image).not.toBeNull();
|
||||
image?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(openSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1057,6 +1057,55 @@ describe("chat view", () => {
|
||||
expect(container.textContent).not.toContain("MEDIA:https://example.com/photo.png");
|
||||
});
|
||||
|
||||
it("opens only safe assistant image URLs in a hardened new tab", () => {
|
||||
const container = document.createElement("div");
|
||||
const openSpy = vi.spyOn(window, "open").mockReturnValue(null);
|
||||
const renderAssistantImage = (url: string) =>
|
||||
render(
|
||||
renderChat(
|
||||
createProps({
|
||||
messages: [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "image_url", image_url: { url } }],
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
container,
|
||||
);
|
||||
|
||||
try {
|
||||
renderAssistantImage("https://example.com/cat.png");
|
||||
let image = container.querySelector<HTMLImageElement>(".chat-message-image");
|
||||
expect(image).not.toBeNull();
|
||||
image?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
|
||||
expect(openSpy).toHaveBeenCalledTimes(1);
|
||||
expect(openSpy).toHaveBeenCalledWith(
|
||||
"https://example.com/cat.png",
|
||||
"_blank",
|
||||
"noopener,noreferrer",
|
||||
);
|
||||
|
||||
openSpy.mockClear();
|
||||
renderAssistantImage("javascript:alert(1)");
|
||||
image = container.querySelector<HTMLImageElement>(".chat-message-image");
|
||||
expect(image).not.toBeNull();
|
||||
image?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
expect(openSpy).not.toHaveBeenCalled();
|
||||
|
||||
renderAssistantImage("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' />");
|
||||
image = container.querySelector<HTMLImageElement>(".chat-message-image");
|
||||
expect(image).not.toBeNull();
|
||||
image?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
expect(openSpy).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
openSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("renders verified local assistant attachments through the Control UI media route", async () => {
|
||||
resetAssistantAttachmentAvailabilityCacheForTest();
|
||||
const fetchMock = vi.fn(async (url: string) => {
|
||||
|
||||
Reference in New Issue
Block a user