import { readFileSync, readdirSync, statSync } from 'node:fs'; import { createRequire } from 'node:module'; import { extname, join, resolve } from 'node:path'; const workspaceRoot = resolve(import.meta.dirname, '..', '..'); const rootLock = JSON.parse(readFileSync(join(workspaceRoot, 'package-lock.json'), 'utf8')); const apiLock = JSON.parse(readFileSync(join(workspaceRoot, 'api', 'package-lock.json'), 'utf8')); assertVersionAtLeast(rootLock.packages['node_modules/postcss']?.version, [8, 5, 18], 'postcss'); assertVersionAtLeast(rootLock.packages['node_modules/react-router']?.version, [7, 18, 2], 'react-router'); assertVersionAtLeast(rootLock.packages['node_modules/nanoid']?.version, [3, 3, 18], 'nanoid'); assertEqual(apiLock.packages['node_modules/brace-expansion-safe']?.version, '5.0.9', 'brace-expansion-safe'); assertEqual(apiLock.packages['node_modules/fast-uri']?.version, '3.1.5', 'fast-uri'); assertEqual(apiLock.packages['node_modules/js-yaml']?.version, '4.3.1', 'js-yaml'); assertEqual(apiLock.packages['node_modules/@nestjs/swagger']?.version, '11.4.7', '@nestjs/swagger'); assertEqual( apiLock.packages['node_modules/brace-expansion']?.resolved, 'vendor/brace-expansion-compat', 'brace-expansion compatibility adapter', ); const forbiddenRscPatterns = [ /\bunstable_RSC\w*/u, /\bRSCRouterConfig\b/u, /\bRSCStaticRouter\b/u, /\bcreateCallServer\b/u, /react-router\/dom\/server/u, ]; for (const filePath of sourceFiles(join(workspaceRoot, 'src'))) { const source = readFileSync(filePath, 'utf8'); for (const pattern of forbiddenRscPatterns) { if (pattern.test(source)) { throw new Error(`React Router RSC mitigation violated by ${filePath}: ${pattern}`); } } } const apiRequire = createRequire(join(workspaceRoot, 'api', 'package.json')); const expand = apiRequire('brace-expansion'); if (typeof expand !== 'function' || expand.EXPANSION_MAX_LENGTH !== 4_000_000) { throw new Error('brace-expansion compatibility adapter is not using the bounded 5.0.9 implementation'); } assertEqual(expand('{a,b}{1,2}').join(','), 'a1,a2,b1,b2', 'brace-expansion legacy API'); for (const relativePath of [ 'node_modules/archiver-utils/node_modules/minimatch', 'node_modules/readdir-glob/node_modules/minimatch', 'node_modules/rimraf/node_modules/minimatch', ]) { const loaded = apiRequire(join(workspaceRoot, 'api', relativePath)); const match = typeof loaded === 'function' ? loaded : loaded.minimatch; if (typeof match !== 'function' || !match('file-a.xlsx', 'file-{a,b}.xlsx')) { throw new Error(`Legacy minimatch compatibility failed for ${relativePath}`); } } console.log( 'Dependency mitigations verified: frontend baselines, Swagger YAML/URI parsers and bounded brace expansion are patched.', ); function sourceFiles(directory) { return readdirSync(directory).flatMap((name) => { const path = join(directory, name); if (statSync(path).isDirectory()) return sourceFiles(path); return ['.js', '.jsx', '.ts', '.tsx'].includes(extname(path)) ? [path] : []; }); } function assertVersionAtLeast(actual, minimum, label) { if (!actual) throw new Error(`${label} is missing from package-lock.json`); const parts = actual.split('.').map((part) => Number(part.replace(/\D.*$/u, ''))); if ( minimum.some( (value, index) => parts[index] < value && minimum.slice(0, index).every((item, i) => parts[i] === item), ) ) { throw new Error(`${label} ${actual} is older than ${minimum.join('.')}`); } } function assertEqual(actual, expected, label) { if (actual !== expected) throw new Error(`${label}: expected ${expected}, received ${actual ?? 'missing'}`); }