import { afterEach, describe, expect, it, vi } from
"vitest" ;
import { openExternalUrlSafe, resolveSafeExternalUrl } from
"./open-external-url.ts" ;
afterEach(() => {
vi.restoreAllMocks();
vi.unstubAllGlobals();
});
describe(
"resolveSafeExternalUrl" , () => {
const baseHref =
"https://openclaw.ai/chat ";
it(
"allows absolute https URLs" , () => {
expect(resolveSafeExternalUrl(
"https://example.com/a.png?x=1#y ", baseHref)).toBe(
"https://example.com/a.png?x=1#y ",
);
});
it(
"allows relative URLs resolved against the current origin" , () => {
expect(resolveSafeExternalUrl(
"/assets/pic.png" , baseHref)).toBe(
"https://openclaw.ai/assets/pic.png ",
);
});
it(
"allows blob URLs" , () => {
expect(resolveSafeExternalUrl(
"blob:https://openclaw.ai/abc-123 ", baseHref)).toBe(
"blob:https://openclaw.ai/abc-123 ",
);
});
it(
"allows data image URLs when enabled" , () => {
expect(
resolveSafeExternalUrl(
"data:image/png;base64,iVBORw0KGgo=" , baseHref, {
allowDataImage:
true ,
}),
).toBe(
"data:image/png;base64,iVBORw0KGgo=" );
});
it(
"rejects non-image data URLs" , () => {
expect(
resolveSafeExternalUrl(
"data:text/html,<script>alert(1)</script>" , baseHref, {
allowDataImage:
true ,
}),
).toBeNull();
});
it(
"rejects SVG data image URLs" , () => {
expect(
resolveSafeExternalUrl(
"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg ' />",
baseHref,
{
allowDataImage:
true ,
},
),
).toBeNull();
});
it(
"rejects base64-encoded SVG data image URLs" , () => {
expect(
resolveSafeExternalUrl(
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIC8+" ,
baseHref,
{
allowDataImage:
true ,
},
),
).toBeNull();
});
it(
"rejects data image URLs unless explicitly enabled" , () => {
expect(resolveSafeExternalUrl(
"data:image/png;base64,iVBORw0KGgo=" , baseHref)).to
BeNull();
});
it("rejects javascript URLs" , () => {
expect(resolveSafeExternalUrl("javascript:alert(1)" , baseHref)).toBeNull();
});
it("rejects file URLs" , () => {
expect(resolveSafeExternalUrl("file:///tmp/x.png", baseHref)).toBeNull();
});
it("rejects empty values" , () => {
expect(resolveSafeExternalUrl(" " , baseHref)).toBeNull();
});
});
describe("openExternalUrlSafe" , () => {
it("nulls opener when window.open returns a proxy-like object" , () => {
const openedLikeProxy = {
opener: { postMessage: () => void 0 },
} as unknown as WindowProxy;
const openMock = vi
.spyOn(window, "open" )
.mockImplementation(() => openedLikeProxy as unknown as Window);
const opened = openExternalUrlSafe("https://example.com/safe.png ", {
baseHref: "https://openclaw.ai/chat ",
});
expect(openMock).toHaveBeenCalledWith(
"https://example.com/safe.png ",
"_blank" ,
"noopener,noreferrer" ,
);
expect(opened).toBe(openedLikeProxy);
expect(openedLikeProxy.opener).toBeNull();
});
});
Messung V0.5 in Prozent C=99 H=98 G=98
¤ Dauer der Verarbeitung: 0.58 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland