import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vitest'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const dockerfile = fs.readFileSync(path.join(root, 'Dockerfile'), 'utf8'); const setupScript = fs.readFileSync( path.join(root, 'scripts/setup-novnc.sh'), 'utf8', ); function readPins(source) { return { version: source.match(/\bNOVNC_VERSION(?:=|:-)([0-9.]+)/)?.[1], sha256: source.match(/\bNOVNC_SHA256(?:=|:-)([a-f0-9]{64})/)?.[1], }; } describe('noVNC bootstrap integrity', () => { it('keeps Dockerfile and setup script pins identical', () => { expect(readPins(setupScript)).toEqual(readPins(dockerfile)); expect(readPins(setupScript).sha256).toMatch(/^[a-f0-9]{64}$/); }); it('checks SHA-256 before replacing the existing vendor directory', () => { const checksum = setupScript.indexOf('sha256sum -c -'); const replacement = setupScript.indexOf('mv "$TMP_NOVNC_DIR" "$NOVNC_DIR"'); expect(checksum).toBeGreaterThan(-1); expect(replacement).toBeGreaterThan(checksum); }); it('pins the npm fallback and disables lifecycle scripts in the project', () => { const projectDir = setupScript.indexOf('PROJECT_DIR='); const npmCheck = setupScript.indexOf('require.resolve("@novnc/novnc/package.json")'); const policy = setupScript.indexOf("node scripts/security/dependency-policy.mjs"); const npmInstall = setupScript.indexOf("npm ci --ignore-scripts --no-audit"); const rebuild = setupScript.indexOf("node scripts/security/rebuild-native.mjs"); expect(projectDir).toBeGreaterThan(-1); expect(npmCheck).toBeGreaterThan(projectDir); expect(policy).toBeGreaterThan(npmCheck); expect(npmInstall).toBeGreaterThan(policy); expect(rebuild).toBeGreaterThan(npmInstall); expect(setupScript).not.toContain('npm install @novnc/novnc'); }); });