diff options
author | Bradley Farias <bradley.meck@gmail.com> | 2018-09-13 14:27:12 -0500 |
---|---|---|
committer | Bradley Farias <bradley.meck@gmail.com> | 2019-01-17 09:43:42 -0600 |
commit | 9d5fbeb55fb1927928237e09475d39346d9c3ad9 (patch) | |
tree | ca2f567ff647c9a1706f39e93e54caa03cd98c1d /test/parallel/test-policy-integrity.js | |
parent | 7b6e9aedaf8c9aa219ff759bed6b1680910eefe0 (diff) | |
download | android-node-v8-9d5fbeb55fb1927928237e09475d39346d9c3ad9.tar.gz android-node-v8-9d5fbeb55fb1927928237e09475d39346d9c3ad9.tar.bz2 android-node-v8-9d5fbeb55fb1927928237e09475d39346d9c3ad9.zip |
policy: manifest with subresource integrity checks
This enables code loaded via the module system to be checked for
integrity to ensure the code loaded matches expectations.
PR-URL: https://github.com/nodejs/node/pull/23834
Reviewed-By: Guy Bedford <guybedford@gmail.com>
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'test/parallel/test-policy-integrity.js')
-rw-r--r-- | test/parallel/test-policy-integrity.js | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/test/parallel/test-policy-integrity.js b/test/parallel/test-policy-integrity.js new file mode 100644 index 0000000000..5c1ea4fc4e --- /dev/null +++ b/test/parallel/test-policy-integrity.js @@ -0,0 +1,297 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const crypto = require('crypto'); +const fs = require('fs'); +const path = require('path'); +const { pathToFileURL } = require('url'); + +tmpdir.refresh(); + +function hash(algo, body) { + const h = crypto.createHash(algo); + h.update(body); + return h.digest('base64'); +} + +const policyFilepath = path.join(tmpdir.path, 'policy'); + +const packageFilepath = path.join(tmpdir.path, 'package.json'); +const packageURL = pathToFileURL(packageFilepath); +const packageBody = '{"main": "dep.js"}'; +const policyToPackageRelativeURLString = `./${ + path.relative(path.dirname(policyFilepath), packageFilepath) +}`; + +const parentFilepath = path.join(tmpdir.path, 'parent.js'); +const parentURL = pathToFileURL(parentFilepath); +const parentBody = 'require(\'./dep.js\')'; + +const depFilepath = path.join(tmpdir.path, 'dep.js'); +const depURL = pathToFileURL(depFilepath); +const depBody = ''; +const policyToDepRelativeURLString = `./${ + path.relative(path.dirname(policyFilepath), depFilepath) +}`; + +fs.writeFileSync(parentFilepath, parentBody); +fs.writeFileSync(depFilepath, depBody); + +const tmpdirURL = pathToFileURL(tmpdir.path); +if (!tmpdirURL.pathname.endsWith('/')) { + tmpdirURL.pathname += '/'; +} +function test({ + shouldFail = false, + entry, + onerror, + resources = {} +}) { + const manifest = { + onerror, + resources: {} + }; + for (const [url, { body, match }] of Object.entries(resources)) { + manifest.resources[url] = { + integrity: `sha256-${hash('sha256', match ? body : body + '\n')}` + }; + fs.writeFileSync(new URL(url, tmpdirURL.href), body); + } + fs.writeFileSync(policyFilepath, JSON.stringify(manifest, null, 2)); + const { status } = spawnSync(process.execPath, [ + '--experimental-policy', policyFilepath, entry + ]); + if (shouldFail) { + assert.notStrictEqual(status, 0); + } else { + assert.strictEqual(status, 0); + } +} + +const { status } = spawnSync(process.execPath, [ + '--experimental-policy', policyFilepath, + '--experimental-policy', policyFilepath +], { + stdio: 'pipe' +}); +assert.notStrictEqual(status, 0, 'Should not allow multiple policies'); + +test({ + shouldFail: true, + entry: parentFilepath, + resources: { + } +}); +test({ + shouldFail: false, + entry: parentFilepath, + onerror: 'log', +}); +test({ + shouldFail: true, + entry: parentFilepath, + onerror: 'exit', +}); +test({ + shouldFail: true, + entry: parentFilepath, + onerror: 'throw', +}); +test({ + shouldFail: true, + entry: parentFilepath, + onerror: 'unknown-onerror-value', +}); +test({ + shouldFail: true, + entry: path.dirname(packageFilepath), + resources: { + } +}); +test({ + shouldFail: true, + entry: path.dirname(packageFilepath), + resources: { + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: false, + entry: path.dirname(packageFilepath), + onerror: 'log', + resources: { + [packageURL]: { + body: packageBody, + match: false, + }, + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: true, + entry: path.dirname(packageFilepath), + resources: { + [packageURL]: { + body: packageBody, + match: false, + }, + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: true, + entry: path.dirname(packageFilepath), + resources: { + [packageURL]: { + body: packageBody, + match: true, + }, + [depURL]: { + body: depBody, + match: false, + } + } +}); +test({ + shouldFail: false, + entry: path.dirname(packageFilepath), + resources: { + [packageURL]: { + body: packageBody, + match: true, + }, + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: false, + entry: parentFilepath, + resources: { + [parentURL]: { + body: parentBody, + match: true, + }, + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: true, + entry: parentFilepath, + resources: { + [parentURL]: { + body: parentBody, + match: false, + }, + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: true, + entry: parentFilepath, + resources: { + [parentURL]: { + body: parentBody, + match: true, + }, + [depURL]: { + body: depBody, + match: false, + } + } +}); +test({ + shouldFail: true, + entry: parentFilepath, + resources: { + [parentURL]: { + body: parentBody, + match: true, + } + } +}); +test({ + shouldFail: false, + entry: depFilepath, + resources: { + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: false, + entry: depFilepath, + resources: { + [policyToDepRelativeURLString]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: true, + entry: depFilepath, + resources: { + [policyToDepRelativeURLString]: { + body: depBody, + match: false, + } + } +}); +test({ + shouldFail: false, + entry: depFilepath, + resources: { + [policyToDepRelativeURLString]: { + body: depBody, + match: true, + }, + [depURL]: { + body: depBody, + match: true, + } + } +}); +test({ + shouldFail: true, + entry: depFilepath, + resources: { + [policyToPackageRelativeURLString]: { + body: packageBody, + match: true, + }, + [packageURL]: { + body: packageBody, + match: true, + }, + [depURL]: { + body: depBody, + match: false, + } + } +}); |