mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-30 08:13:37 +00:00
* fix(diffs): replace iconMarkup string with ToolbarIconName enum to eliminate XSS sink Replace createToolbarButton's iconMarkup: string parameter with icon: ToolbarIconName, a union of known icon names. SVG generation moves into a sealed toolbarIconSvg map so innerHTML only receives compile-time-known strings. The old splitIcon/unifiedIcon/ wrapIcon/backgroundIcon/themeIcon functions are removed; callers now pass icon name literals instead of raw markup strings. Closes #83918 * fix(diffs): remove jsdom dependency from viewer-client test Use source file string analysis instead of jsdom to avoid missing @types/jsdom declaration error in check-test-types CI job. * fix(diffs): restore wrap icon arrow segment in ToolbarIconName map The wrap-on and wrap-off SVG paths were missing the original wrap arrow segment (M14 6h-4V5h4.5...). Restore the exact original path data and rebuild the viewer runtime bundle. * build(diffs): refresh viewer runtime after rebase --------- Co-authored-by: tanshanshan <tanshanshan@users.noreply.github.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const VIEWER_CLIENT_SRC = readFileSync(
|
|
new URL("./viewer-client.ts", import.meta.url),
|
|
"utf8",
|
|
);
|
|
|
|
const XSS_PATTERNS = ["onerror", "<script", "onclick", "javascript:", "onload"];
|
|
|
|
describe("createToolbarButton icon safety", () => {
|
|
it("toolbarIconSvg map exists and has exactly 8 icon names", () => {
|
|
const requiredNames = [
|
|
"split",
|
|
"unified",
|
|
"wrap-on",
|
|
"wrap-off",
|
|
"background-on",
|
|
"background-off",
|
|
"theme-dark",
|
|
"theme-light",
|
|
] as const;
|
|
for (const name of requiredNames) {
|
|
expect(
|
|
VIEWER_CLIENT_SRC.includes(name + ":") || VIEWER_CLIENT_SRC.includes(`"${name}"`),
|
|
`icon "${name}" should exist in toolbarIconSvg`,
|
|
).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("no iconMarkup: string parameter exists", () => {
|
|
expect(VIEWER_CLIENT_SRC.includes("iconMarkup: string")).toBe(false);
|
|
});
|
|
|
|
it("innerHTML reads only from toolbarIconSvg lookup", () => {
|
|
expect(VIEWER_CLIENT_SRC.includes("button.innerHTML = toolbarIconSvg[params.icon]")).toBe(true);
|
|
});
|
|
|
|
it("SVG strings in toolbarIconSvg contain no XSS patterns", () => {
|
|
for (const pattern of XSS_PATTERNS) {
|
|
expect(
|
|
VIEWER_CLIENT_SRC.includes(pattern),
|
|
`source must not contain "${pattern}"`,
|
|
).toBe(false);
|
|
}
|
|
});
|
|
|
|
it("old icon functions are removed", () => {
|
|
const removedFunctions = [
|
|
"function splitIcon(",
|
|
"function unifiedIcon(",
|
|
"function wrapIcon(",
|
|
"function backgroundIcon(",
|
|
"function themeIcon(",
|
|
];
|
|
for (const fn of removedFunctions) {
|
|
expect(VIEWER_CLIENT_SRC.includes(fn), `"${fn}" should be removed`).toBe(false);
|
|
}
|
|
});
|
|
});
|