1'use strict';
2const common = require('../common');
3if (process.platform !== 'darwin')
4  common.skip('App Sandbox is only available on Darwin');
5if (process.config.variables.node_builtin_modules_path)
6  common.skip('App Sandbox cannot load modules from outside the sandbox');
7
8const fixtures = require('../common/fixtures');
9const tmpdir = require('../common/tmpdir');
10const assert = require('assert');
11const child_process = require('child_process');
12const path = require('path');
13const fs = require('fs');
14const os = require('os');
15
16const nodeBinary = process.execPath;
17
18tmpdir.refresh();
19
20const appBundlePath = path.join(tmpdir.path, 'node_sandboxed.app');
21const appBundleContentPath = path.join(appBundlePath, 'Contents');
22const appExecutablePath = path.join(
23  appBundleContentPath, 'MacOS', 'node');
24
25// Construct the app bundle and put the node executable in it:
26// node_sandboxed.app/
27// └── Contents
28//     ├── Info.plist
29//     ├── MacOS
30//     │   └── node
31fs.mkdirSync(appBundlePath);
32fs.mkdirSync(appBundleContentPath);
33fs.mkdirSync(path.join(appBundleContentPath, 'MacOS'));
34fs.copyFileSync(
35  fixtures.path('macos-app-sandbox', 'Info.plist'),
36  path.join(appBundleContentPath, 'Info.plist'));
37fs.copyFileSync(
38  nodeBinary,
39  appExecutablePath);
40
41
42// Sign the app bundle with sandbox entitlements:
43assert.strictEqual(
44  child_process.spawnSync('/usr/bin/codesign', [
45    '--entitlements', fixtures.path(
46      'macos-app-sandbox', 'node_sandboxed.entitlements'),
47    '--force', '-s', '-',
48    appBundlePath,
49  ]).status,
50  0);
51
52// Sandboxed app shouldn't be able to read the home dir
53assert.notStrictEqual(
54  child_process.spawnSync(appExecutablePath, [
55    '-e', 'fs.readdirSync(process.argv[1])', os.homedir(),
56  ]).status,
57  0);
58
59if (process.stdin.isTTY) {
60  // Run the sandboxed node instance with inherited tty stdin
61  const spawnResult = child_process.spawnSync(
62    appExecutablePath, ['-e', ''],
63    { stdio: 'inherit' }
64  );
65
66  assert.strictEqual(spawnResult.signal, null);
67}
68