Spaces:
Running
Running
File size: 2,667 Bytes
704e84f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #!/usr/bin/env node
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();
|