70 lines
1.8 KiB
JavaScript
70 lines
1.8 KiB
JavaScript
import { spawnSync } from 'node:child_process';
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import { checkLockfilePolicy } from './dependency-policy.mjs';
|
|
import { validateRebuildEntries } from './rebuild-native.mjs';
|
|
|
|
const lockedNative = {
|
|
lockfileVersion: 3,
|
|
packages: {
|
|
'node_modules/better-sqlite3': {
|
|
version: '12.6.2',
|
|
resolved: 'https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.6.2.tgz',
|
|
integrity: 'sha512-approved',
|
|
hasInstallScript: true,
|
|
},
|
|
},
|
|
};
|
|
|
|
function approval(name) {
|
|
return [{
|
|
path: 'node_modules/better-sqlite3',
|
|
name,
|
|
version: '12.6.2',
|
|
integrity: 'sha512-approved',
|
|
verifier: 'better-sqlite3-memory-db',
|
|
}];
|
|
}
|
|
|
|
describe('native rebuild adversarial cases', () => {
|
|
it('rejects a package name that does not match the approved lockfile path', () => {
|
|
expect(() => validateRebuildEntries(lockedNative, approval('sharp'))).toThrow(
|
|
/name mismatch/i,
|
|
);
|
|
});
|
|
|
|
it('rejects npm option injection as a package name', () => {
|
|
expect(() => validateRebuildEntries(lockedNative, approval('--prefix=/tmp/evil'))).toThrow(
|
|
/invalid package name|name mismatch/i,
|
|
);
|
|
});
|
|
|
|
it('rejects lockfile links because this repository has no workspaces', () => {
|
|
const violations = checkLockfilePolicy(
|
|
{
|
|
lockfileVersion: 3,
|
|
packages: {
|
|
'node_modules/evil': { link: true },
|
|
},
|
|
},
|
|
[],
|
|
);
|
|
|
|
expect(violations).toContainEqual({
|
|
code: 'unsupported-link',
|
|
name: 'node_modules/evil',
|
|
});
|
|
});
|
|
|
|
it('can be imported when a Node eval has no script argv', () => {
|
|
const result = spawnSync(
|
|
process.execPath,
|
|
['-e', "import('./scripts/security/rebuild-native.mjs')"],
|
|
{ cwd: process.cwd(), encoding: 'utf8' },
|
|
);
|
|
|
|
expect(result.status, result.stderr).toBe(0);
|
|
});
|
|
});
|