summaryrefslogtreecommitdiff
path: root/test/parallel/test-policy-integrity.js
diff options
context:
space:
mode:
authorBradley Farias <bradley.meck@gmail.com>2018-09-13 14:27:12 -0500
committerBradley Farias <bradley.meck@gmail.com>2019-01-17 09:43:42 -0600
commit9d5fbeb55fb1927928237e09475d39346d9c3ad9 (patch)
treeca2f567ff647c9a1706f39e93e54caa03cd98c1d /test/parallel/test-policy-integrity.js
parent7b6e9aedaf8c9aa219ff759bed6b1680910eefe0 (diff)
downloadandroid-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.js297
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,
+ }
+ }
+});