Skip to content

Commit cdbb6c3

Browse files
committed
[green] Eliminate website dependency advisories
Signed-off-by: Viwat Vchirawongkwin <viwat.v@chula.ac.th>
1 parent e3e4300 commit cdbb6c3

6 files changed

Lines changed: 307 additions & 51 deletions

File tree

‎tools/web/package-lock.json‎

Lines changed: 9 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tools/web/package.json‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"build:sites": "node scripts/assert-no-local-firmware-preview.js && vinext build && node scripts/prepare-sites-output.js",
1515
"firmware:stage": "node scripts/stage-firmware-release.js",
1616
"firmware:preview": "node scripts/stage-local-firmware-preview.js",
17+
"postinstall": "node scripts/patch-vinext-image-size.js",
18+
"audit:dependencies": "npm audit --audit-level=high",
1719
"licenses:web": "node scripts/generate-website-third-party-licenses.js --check",
1820
"start": "vinext start",
1921
"lint": "eslint . --max-warnings=0",
@@ -22,7 +24,7 @@
2224
"test:watch": "vitest",
2325
"vinext:check": "vinext check",
2426
"format:check": "prettier --check .",
25-
"check": "npm run format:check && npm run lint && npm run typecheck && npm run licenses:web && npm test && npm run vinext:check && npm run build"
27+
"check": "npm run format:check && npm run lint && npm run typecheck && npm run audit:dependencies && npm run licenses:web && npm test && npm run vinext:check && npm run build"
2628
},
2729
"dependencies": {
2830
"@material/web": "2.2.0",
@@ -31,7 +33,7 @@
3133
"react": "19.2.8",
3234
"react-dom": "19.2.8",
3335
"react-server-dom-webpack": "19.2.8",
34-
"vinext": "1.0.0-beta.4"
36+
"vinext": "1.0.0-beta.8"
3537
},
3638
"devDependencies": {
3739
"@eslint/js": "10.0.1",
@@ -42,7 +44,7 @@
4244
"@types/react": "19.2.17",
4345
"@types/react-dom": "19.2.3",
4446
"@vitejs/plugin-react": "6.0.4",
45-
"@vitejs/plugin-rsc": "0.5.32",
47+
"@vitejs/plugin-rsc": "0.5.34",
4648
"eslint": "10.8.0",
4749
"eslint-plugin-react-hooks": "7.1.1",
4850
"globals": "17.8.0",

‎tools/web/public/WEBSITE_THIRD_PARTY_LICENSES.txt‎

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3403,23 +3403,6 @@ The above copyright notice and this permission notice shall be included in all c
34033403

34043404
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34053405

3406-
================================================================================
3407-
image-size 2.0.2
3408-
Installed path: node_modules/image-size
3409-
SPDX license: MIT
3410-
Source: https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz
3411-
License file: LICENSE
3412-
3413-
The MIT License (MIT)
3414-
3415-
Copyright © 2013-Present Aditya Yadav, http://netroy.in
3416-
3417-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3418-
3419-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
3420-
3421-
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3422-
34233406
================================================================================
34243407
improv-wifi-serial-sdk 2.8.0
34253408
Installed path: node_modules/improv-wifi-serial-sdk
@@ -5097,10 +5080,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50975080
SOFTWARE.
50985081

50995082
================================================================================
5100-
vinext 1.0.0-beta.4
5083+
vinext 1.0.0-beta.8
51015084
Installed path: node_modules/vinext
51025085
SPDX license: MIT
5103-
Source: https://registry.npmjs.org/vinext/-/vinext-1.0.0-beta.4.tgz
5086+
Source: https://registry.npmjs.org/vinext/-/vinext-1.0.0-beta.8.tgz
51045087
License file: LICENSE
51055088

51065089
MIT License
@@ -5450,3 +5433,32 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54505433
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54515434
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54525435
SOFTWARE.
5436+
5437+
================================================================================
5438+
image-size 2.0.2 (bundled by vinext 1.0.0-beta.8)
5439+
Bundled path: node_modules/vinext/dist/deps/.pnpm/image-size@2.0.2/deps/image-size/dist/index.js
5440+
SPDX license: MIT
5441+
Source: https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz
5442+
License file: reviewed image-size@2.0.2 package LICENSE
5443+
5444+
The MIT License (MIT)
5445+
5446+
Copyright © 2013-Present Aditya Yadav, http://netroy.in
5447+
5448+
Permission is hereby granted, free of charge, to any person obtaining a copy
5449+
of this software and associated documentation files (the "Software"), to deal
5450+
in the Software without restriction, including without limitation the rights
5451+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5452+
copies of the Software, and to permit persons to whom the Software is
5453+
furnished to do so, subject to the following conditions:
5454+
5455+
The above copyright notice and this permission notice shall be included in all
5456+
copies or substantial portions of the Software.
5457+
5458+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5459+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5460+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5461+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5462+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5463+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5464+
SOFTWARE.

‎tools/web/scripts/generate-website-third-party-licenses.js‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,23 @@ const reviewedLicenseSources = {
9797
path: "node_modules/lightningcss/LICENSE",
9898
},
9999
};
100+
const bundledProductionDependencies = [
101+
{
102+
ownerPath: "node_modules/vinext",
103+
ownerVersion: "1.0.0-beta.8",
104+
name: "image-size",
105+
version: "2.0.2",
106+
bundledPath:
107+
"node_modules/vinext/dist/deps/.pnpm/image-size@2.0.2/deps/image-size/dist/index.js",
108+
license: "MIT",
109+
source: "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz",
110+
licenseName: "reviewed image-size@2.0.2 package LICENSE",
111+
licenseText: mitLicense(
112+
"Copyright © 2013-Present Aditya Yadav, http://netroy.in",
113+
"The MIT License (MIT)",
114+
),
115+
},
116+
];
100117

101118
function packageNameFromPath(packagePath) {
102119
const marker = "node_modules/";
@@ -303,6 +320,29 @@ export async function generateWebsiteThirdPartyLicenses() {
303320
);
304321
}
305322

323+
for (const bundled of bundledProductionDependencies) {
324+
const owner = lock.packages[bundled.ownerPath];
325+
if (owner?.version !== bundled.ownerVersion) {
326+
throw new Error(
327+
`Reviewed bundled dependency record is stale for ${bundled.ownerPath}@${owner?.version ?? "missing"}`,
328+
);
329+
}
330+
await readFile(join(packageRoot, bundled.bundledPath), "utf8");
331+
records.push(
332+
[
333+
"================================================================================",
334+
`${bundled.name} ${bundled.version} (bundled by vinext ${bundled.ownerVersion})`,
335+
`Bundled path: ${bundled.bundledPath}`,
336+
`SPDX license: ${bundled.license}`,
337+
`Source: ${bundled.source}`,
338+
`License file: ${bundled.licenseName}`,
339+
"",
340+
bundled.licenseText,
341+
"",
342+
].join("\n"),
343+
);
344+
}
345+
306346
return [
307347
"PyBLE website third-party notices",
308348
"====================================",
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// SPDX-License-Identifier: MIT
2+
// Part of PyBLE (https://pyble.dev) — see /LICENSE.
3+
4+
import { readFile, writeFile } from "node:fs/promises";
5+
import { join, resolve } from "node:path";
6+
import { fileURLToPath, pathToFileURL } from "node:url";
7+
8+
const packageRoot = fileURLToPath(new URL("..", import.meta.url));
9+
const bundledParserPath = join(
10+
packageRoot,
11+
"node_modules",
12+
"vinext",
13+
"dist",
14+
"deps",
15+
".pnpm",
16+
"image-size@2.0.2",
17+
"deps",
18+
"image-size",
19+
"dist",
20+
"index.js",
21+
);
22+
23+
const hardeningEdits = [
24+
{
25+
advisory: "GHSA-w3rx-r6r6-pgpr",
26+
before:
27+
"\t\t\tconst imageHeader = readImageHeader(input, imageOffset);\n\t\t\tconst imageSize2 = getImageSize2(imageHeader[0]);",
28+
after:
29+
'\t\t\tconst imageHeader = readImageHeader(input, imageOffset);\n\t\t\tif (imageHeader[1] <= 0) throw new TypeError("Invalid ICNS, zero-length image entry");\n\t\t\tconst imageSize2 = getImageSize2(imageHeader[0]);',
30+
},
31+
{
32+
advisory: "GHSA-5p2g-fcmc-qvqq (HEIF)",
33+
before:
34+
'\t\t\tconst ispeBox = findBox(input, "ispe", currentOffset);\n\t\t\tif (!ispeBox) break;\n\t\t\tconst rawWidth = readUInt32BE(input, ispeBox.offset + 12);',
35+
after:
36+
'\t\t\tconst ispeBox = findBox(input, "ispe", currentOffset);\n\t\t\tif (!ispeBox) break;\n\t\t\tif (ispeBox.size <= 0) throw new TypeError("Invalid HEIF, zero-length ispe box");\n\t\t\tconst rawWidth = readUInt32BE(input, ispeBox.offset + 12);',
37+
},
38+
{
39+
advisory: "GHSA-5p2g-fcmc-qvqq (JXL)",
40+
before:
41+
'\t\tconst jxlpBox = findBox(input, "jxlp", offset);\n\t\tif (!jxlpBox) break;\n\t\tpartialStreams.push(input.slice(jxlpBox.offset + 12, jxlpBox.offset + jxlpBox.size));',
42+
after:
43+
'\t\tconst jxlpBox = findBox(input, "jxlp", offset);\n\t\tif (!jxlpBox) break;\n\t\tif (jxlpBox.size <= 0) throw new TypeError("Invalid JXL, zero-length jxlp box");\n\t\tpartialStreams.push(input.slice(jxlpBox.offset + 12, jxlpBox.offset + jxlpBox.size));',
44+
},
45+
];
46+
47+
/**
48+
* @param {string} source
49+
* @returns {string}
50+
*/
51+
export function hardenBundledImageSize(source) {
52+
let hardened = source;
53+
for (const edit of hardeningEdits) {
54+
const hardenedOccurrences = hardened.split(edit.after).length - 1;
55+
const vulnerableOccurrences = hardened.split(edit.before).length - 1;
56+
if (hardenedOccurrences === 1 && vulnerableOccurrences === 0) {
57+
continue;
58+
}
59+
if (hardenedOccurrences !== 0 || vulnerableOccurrences !== 1) {
60+
throw new Error(
61+
`Cannot apply ${edit.advisory} hardening: found ${vulnerableOccurrences} vulnerable and ${hardenedOccurrences} hardened matches`,
62+
);
63+
}
64+
hardened = hardened.replace(edit.before, edit.after);
65+
}
66+
return hardened;
67+
}
68+
69+
async function run() {
70+
const source = await readFile(bundledParserPath, "utf8");
71+
const hardened = hardenBundledImageSize(source);
72+
if (hardened !== source) {
73+
await writeFile(bundledParserPath, hardened, "utf8");
74+
}
75+
}
76+
77+
const invokedPath = process.argv[1];
78+
if (
79+
invokedPath &&
80+
import.meta.url === pathToFileURL(resolve(invokedPath)).href
81+
) {
82+
run().catch((error) => {
83+
console.error(error instanceof Error ? error.message : error);
84+
process.exitCode = 1;
85+
});
86+
}

0 commit comments

Comments
 (0)