fix: update vulnerable URI CSS and SVG dependency copies

This commit is contained in:
tianma-if committed 2026-10-12 13:29:12 +08:00
1 parent e4ede1dcd4
commit ea4867a173
2 files changed
+67 -6

No files matched your search

+5 -5
View File
@@ -2566,7 +2566,7 @@
"fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="],
"fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="],
"fast-uri": ["fast-uri@3.1.8", "", {}, "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg=="],
"fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="],
@@ -3894,7 +3894,7 @@
"source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"source-map-js": ["source-map-js@1.2.2", "", {}, "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw=="],
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
@@ -4380,7 +4380,7 @@
"@antfu/install-pkg/tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="],
"@antv/infographic/postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
"@antv/infographic/postcss": ["postcss@8.5.29", "", { "dependencies": { "nanoid": "^3.3.19", "picocolors": "^1.1.1", "source-map-js": "^1.2.2" } }, "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ=="],
"@asamuzakjp/css-color/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
@@ -4522,7 +4522,7 @@
"@iconify/tools/domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
"@iconify/tools/svgo": ["svgo@3.3.3", "", { "dependencies": { "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.0.0", "sax": "^1.5.0" }, "bin": "./bin/svgo" }, "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng=="],
"@iconify/tools/svgo": ["svgo@3.3.5", "", { "dependencies": { "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.0.0", "sax": "^1.5.0" }, "bin": "./bin/svgo" }, "sha512-8SQMzdrvWaD8deUmrnYB+ASyxBVgWUOilg+A75nE/76WdLpj6LopCwiAVvkzkcqy/9b7t2Mg7faFLjg0ZRcZ3w=="],
"@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -5316,7 +5316,7 @@
"zip-dir/jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="],
"@antv/infographic/postcss/nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="],
"@antv/infographic/postcss/nanoid": ["nanoid@3.3.20", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ=="],
"@astrojs/check/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+62 -1
View File
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test";
import { createRequire } from "node:module";
import { mkdtempSync, rmSync } from "node:fs";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -8,12 +8,73 @@ const desktopRequire = createRequire(new URL("../apps/desktop/package.json", imp
const rootRequire = createRequire(new URL("../package.json", import.meta.url));
const mobileRequire = createRequire(new URL("../apps/mobile/package.json", import.meta.url));
const extensionRequire = createRequire(new URL("../apps/extension/package.json", import.meta.url));
const webRequire = createRequire(new URL("../apps/web/package.json", import.meta.url));
const siteRequire = createRequire(new URL("../apps/site/package.json", import.meta.url));
function consumerRequire(start, ...packages) {
return packages.reduce((require, name) => createRequire(require.resolve(name)), start);
}
describe("dependency security at the actual consumer", () => {
test("the desktop schema validator canonicalizes percent-encoded hostnames", () => {
const builderRequire = consumerRequire(desktopRequire, "electron-builder", "app-builder-lib");
const ajvRequire = consumerRequire(builderRequire, "ajv");
const uri = ajvRequire("fast-uri");
expect(uri.parse("//%41.com").host).toBe("a.com");
expect(uri.equal("//%41.com", "//a.com")).toBe(true);
const Ajv = builderRequire("ajv");
const validate = new Ajv().compile({ type: "object", properties: { enabled: { type: "boolean" } } });
expect(validate({ enabled: true })).toBe(true);
expect(validate({ enabled: "true" })).toBe(false);
});
test("infographic CSS cannot load an absolute source map without a source filename", () => {
const infographicRequire = consumerRequire(webRequire, "@antv/infographic/package.json");
const postcss = infographicRequire("postcss");
const directory = mkdtempSync(join(tmpdir(), "edgeever-css-map-"));
const mapPath = join(directory, "private.map");
try {
writeFileSync(mapPath, JSON.stringify({ version: 3, sources: ["private.txt"], sourcesContent: ["EDGE_EVER_PRIVATE_MAP_CONTENT"], names: [], mappings: "AAAA" }));
const result = postcss([]).process(`a { color: green }\n/*# sourceMappingURL=${mapPath} */`, { map: { inline: false } }).sync();
expect(result.root.source.input.map?.text).toBeUndefined();
expect(JSON.stringify(result.map.toJSON())).not.toContain("EDGE_EVER_PRIVATE_MAP_CONTENT");
expect(result.css).toContain("color: green");
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("Tailwind's source map consumer rejects excessive indexed offsets", () => {
const tailwindRequire = consumerRequire(rootRequire, "@tailwindcss/vite", "@tailwindcss/node");
const { SourceMapConsumer } = tailwindRequire("source-map-js");
const map = { version: 3, sources: ["input.css"], names: [], mappings: "AAAA" };
expect(new SourceMapConsumer(map).originalPositionFor({ line: 1, column: 0 }).source).toBe("input.css");
expect(() => new SourceMapConsumer({ version: 3, sections: [{ offset: { line: 10000001, column: 0 }, map }] })).toThrow(/offset/i);
});
test("infographic's Nano ID handles non-positive sizes without looping", () => {
const postcssRequire = consumerRequire(webRequire, "@antv/infographic/package.json", "postcss");
const version = postcssRequire("nanoid/package.json").version;
const npmRequire = consumerRequire(desktopRequire, "npm/package.json");
expect(npmRequire("semver").satisfies(version, ">=3.3.18 <4")).toBe(true);
const { nanoid, customAlphabet } = postcssRequire("nanoid/non-secure");
expect(nanoid(-1)).toBe("");
expect(customAlphabet("abc")(0)).toBe("");
expect(customAlphabet("abc")(8)).toMatch(/^[abc]{8}$/);
expect(postcssRequire("nanoid").customAlphabet("abc")(0)).toBe("");
});
test("Iconify's SVGO strips executable namespace-prefixed and obfuscated links", () => {
const iconifyRequire = consumerRequire(siteRequire, "astro-icon/package.json", "@iconify/tools/package.json");
const { optimize } = iconifyRequire("svgo");
const svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:s="http://www.w3.org/2000/svg"><s:script>alert(1)</s:script><s:a href="java&#9;script:alert(1)"><circle r="2"/></s:a><circle r="3" onload="alert(1)"/></svg>';
const output = optimize(svg, { plugins: ["removeScriptElement"] }).data;
expect(output).not.toContain("script");
expect(output).not.toContain("onload");
expect(output).toContain('r="2"');
expect(output).toContain('r="3"');
});
test("native plist consumers preserve values and reject injected entity names", () => {
const expoRequire = consumerRequire(mobileRequire, "expo/package.json", "@expo/config-plugins");
const builderRequire = consumerRequire(desktopRequire, "electron-builder", "app-builder-lib");