1'use strict'; 2 3const common = require('../common'); 4if (!common.hasCrypto) common.skip('missing crypto'); 5common.requireNoPackageJSONAbove(); 6 7const tmpdir = require('../common/tmpdir'); 8const assert = require('assert'); 9const { spawnSync } = require('child_process'); 10const crypto = require('crypto'); 11const fs = require('fs'); 12const path = require('path'); 13const { pathToFileURL } = require('url'); 14 15tmpdir.refresh(); 16 17function hash(algo, body) { 18 const h = crypto.createHash(algo); 19 h.update(body); 20 return h.digest('base64'); 21} 22 23const tmpdirPath = path.join(tmpdir.path, 'test-policy-parse-integrity'); 24fs.rmSync(tmpdirPath, { maxRetries: 3, recursive: true, force: true }); 25fs.mkdirSync(tmpdirPath, { recursive: true }); 26 27const policyFilepath = path.join(tmpdirPath, 'policy'); 28 29const parentFilepath = path.join(tmpdirPath, 'parent.js'); 30const parentBody = "require('./dep.js')"; 31 32const depFilepath = path.join(tmpdirPath, 'dep.js'); 33const depURL = pathToFileURL(depFilepath); 34const depBody = ''; 35 36fs.writeFileSync(parentFilepath, parentBody); 37fs.writeFileSync(depFilepath, depBody); 38 39const tmpdirURL = pathToFileURL(tmpdirPath); 40if (!tmpdirURL.pathname.endsWith('/')) { 41 tmpdirURL.pathname += '/'; 42} 43 44const packageFilepath = path.join(tmpdirPath, 'package.json'); 45const packageURL = pathToFileURL(packageFilepath); 46const packageBody = '{"main": "dep.js"}'; 47 48function test({ shouldFail, integrity, manifest = {} }) { 49 manifest.resources = {}; 50 const resources = { 51 [packageURL]: { 52 body: packageBody, 53 integrity: `sha256-${hash('sha256', packageBody)}` 54 }, 55 [depURL]: { 56 body: depBody, 57 integrity 58 } 59 }; 60 for (const [url, { body, integrity }] of Object.entries(resources)) { 61 manifest.resources[url] = { 62 integrity, 63 }; 64 fs.writeFileSync(new URL(url, tmpdirURL.href), body); 65 } 66 fs.writeFileSync(policyFilepath, JSON.stringify(manifest, null, 2)); 67 const { status } = spawnSync(process.execPath, [ 68 '--experimental-policy', 69 policyFilepath, 70 depFilepath, 71 ]); 72 if (shouldFail) { 73 assert.notStrictEqual(status, 0); 74 } else { 75 assert.strictEqual(status, 0); 76 } 77} 78 79test({ 80 shouldFail: false, 81 integrity: `sha256-${hash('sha256', depBody)}`, 82}); 83test({ 84 shouldFail: true, 85 integrity: `1sha256-${hash('sha256', depBody)}`, 86}); 87test({ 88 shouldFail: true, 89 integrity: 'hoge', 90}); 91test({ 92 shouldFail: true, 93 integrity: `sha256-${hash('sha256', depBody)}sha256-${hash( 94 'sha256', 95 depBody 96 )}`, 97}); 98test({ 99 shouldFail: true, 100 integrity: `sha256-${hash('sha256', 'file:///')}`, 101 manifest: { 102 onerror: 'exit' 103 } 104}); 105test({ 106 shouldFail: false, 107 integrity: `sha256-${hash('sha256', 'file:///')}`, 108 manifest: { 109 onerror: 'log' 110 } 111}); 112