Spaces:
Running
Running
| import { readFileSync } from 'node:fs'; | |
| import { join } from 'node:path'; | |
| import { fileURLToPath } from 'node:url'; | |
| const REPO_ROOT = fileURLToPath(new URL('..', import.meta.url)); | |
| function readJson(path) { | |
| return JSON.parse(readFileSync(join(REPO_ROOT, path), 'utf8')); | |
| } | |
| function extractPackageName(lockfilePath) { | |
| const packagePath = lockfilePath.slice(lockfilePath.lastIndexOf('node_modules/') + 'node_modules/'.length); | |
| if (/^(?:@[^/]+\/)?[^/]+$/.test(packagePath)) return packagePath; | |
| return undefined; | |
| } | |
| export function collectInstallScriptIdentities(packageLock) { | |
| const identities = []; | |
| for (const [lockfilePath, manifest] of Object.entries(packageLock.packages ?? {})) { | |
| if (!lockfilePath.includes('node_modules/') || manifest?.hasInstallScript !== true) continue; | |
| const name = extractPackageName(lockfilePath); | |
| if (!name || typeof manifest.version !== 'string' || manifest.version.length === 0) { | |
| throw new Error(`Invalid install-script package-lock entry: ${lockfilePath}`); | |
| } | |
| identities.push(`${name}@${manifest.version}`); | |
| } | |
| return [...new Set(identities)].sort(); | |
| } | |
| export function validateInstallScriptPolicy(packageLock, packageJson) { | |
| const installScriptIdentities = collectInstallScriptIdentities(packageLock); | |
| const policy = packageJson.allowScripts; | |
| const entries = policy && typeof policy === 'object' && !Array.isArray(policy) ? Object.entries(policy) : []; | |
| const invalid = entries | |
| .filter(([, value]) => typeof value !== 'boolean') | |
| .map(([identity]) => identity) | |
| .sort(); | |
| const approved = entries | |
| .filter(([, value]) => value === true) | |
| .map(([identity]) => identity) | |
| .sort(); | |
| const denied = entries | |
| .filter(([, value]) => value === false) | |
| .map(([identity]) => identity) | |
| .sort(); | |
| const configured = entries.map(([identity]) => identity); | |
| const missing = installScriptIdentities.filter((identity) => !approved.includes(identity)); | |
| const stale = configured.filter((identity) => !installScriptIdentities.includes(identity)).sort(); | |
| return { | |
| ok: missing.length === 0 && stale.length === 0 && invalid.length === 0, | |
| installScriptIdentities, | |
| approved, | |
| denied, | |
| missing, | |
| stale, | |
| invalid | |
| }; | |
| } | |
| function main() { | |
| const result = validateInstallScriptPolicy(readJson('package-lock.json'), readJson('package.json')); | |
| console.log(JSON.stringify(result, null, 2)); | |
| if (!result.ok) process.exit(1); | |
| } | |
| if (process.argv[1] === fileURLToPath(import.meta.url)) main(); | |