|
2 | 2 |
|
3 | 3 | import * as fs from 'node:fs'; |
4 | 4 | import { isBuiltin } from 'node:module'; |
5 | | -import { platform } from 'node:os'; |
6 | 5 | import * as path from 'node:path'; |
7 | 6 | import * as vm from 'node:vm'; |
8 | 7 |
|
| 8 | +const allowedModules = new Set([ |
| 9 | + '@aws-sdk/credential-providers', |
| 10 | + '@mongodb-js/saslprep', |
| 11 | + '@mongodb-js/zstd', |
| 12 | + 'bson', |
| 13 | + 'gcp-metadata', |
| 14 | + 'kerberos', |
| 15 | + 'mongodb-client-encryption', |
| 16 | + 'mongodb-connection-string-url', |
| 17 | + 'path', |
| 18 | + 'snappy' |
| 19 | +]); |
| 20 | +const blockedModules = new Set(['os']); |
| 21 | + |
9 | 22 | /** |
10 | 23 | * Creates a require function that blocks access to specified core modules |
11 | 24 | */ |
12 | 25 | function createRestrictedRequire() { |
13 | | - const blockedModules = new Set(['os']); |
14 | | - const allowedRequesters = [ |
15 | | - { |
16 | | - file: 'runtime_adapters.ts', |
17 | | - method: 'resolveRuntimeAdapters', |
18 | | - module: 'os' |
19 | | - } |
20 | | - ]; |
21 | | - |
22 | 26 | return function restrictedRequire(moduleName: string) { |
23 | | - // Block core modules |
24 | | - if (isBuiltin(moduleName) && blockedModules.has(moduleName)) { |
25 | | - const callStack = new Error().stack; |
26 | | - const correctPath = platform() === 'win32' ? path.win32 : path.posix; |
27 | | - const methodAndFile = callStack.split('\n')[2]; |
28 | | - const match = methodAndFile.match(/at (.*) \((.*)\)/); |
29 | | - const method = match ? match[1] : null; |
30 | | - const sourceFileAndLineNumbers = match ? match[2] : 'unknown'; |
31 | | - const sourceFile = |
32 | | - sourceFileAndLineNumbers.indexOf('.ts:') === -1 |
33 | | - ? sourceFileAndLineNumbers |
34 | | - : sourceFileAndLineNumbers.substring(0, sourceFileAndLineNumbers.lastIndexOf('.ts:') + 3); |
35 | | - const sourceFileName = correctPath.basename(sourceFile); |
36 | | - const isAllowed = allowedRequesters.some( |
37 | | - requester => |
38 | | - requester.file === sourceFileName && |
39 | | - requester.method === method && |
40 | | - requester.module === moduleName |
41 | | - ); |
42 | | - |
43 | | - if (isAllowed) { |
44 | | - // Allow access to the module if the requester is in the allowlist |
45 | | - } else { |
46 | | - throw new Error( |
47 | | - `Access to core module '${moduleName}' from ${sourceFileName} is restricted in this context` |
48 | | - ); |
49 | | - } |
| 27 | + const isModuleBuiltin = isBuiltin(moduleName); |
| 28 | + const isModuleAllowed = allowedModules.has(moduleName); |
| 29 | + const isModuleBlocked = blockedModules.has(moduleName); |
| 30 | + const shouldAllow = isModuleAllowed || isModuleBuiltin; |
| 31 | + const shouldBlock = isModuleBlocked || !shouldAllow; |
| 32 | + |
| 33 | + if (shouldBlock) { |
| 34 | + throw new Error(`Access to core module '${moduleName}' is restricted in this context`); |
50 | 35 | } |
51 | | - |
52 | 36 | return require(moduleName); |
53 | 37 | } as NodeRequire; |
54 | 38 | } |
@@ -77,52 +61,25 @@ const sandbox = vm.createContext({ |
77 | 61 | // Process |
78 | 62 | process: process, |
79 | 63 |
|
| 64 | + // TODO: NODE-7460 - Remove Error and other unnecessary exports |
| 65 | + |
80 | 66 | // Global objects needed for runtime |
81 | 67 | Buffer: Buffer, |
82 | 68 | Headers: global.Headers, |
83 | | - Promise: Promise, |
84 | 69 | Map: Map, |
85 | | - Set: Set, |
86 | | - WeakMap: WeakMap, |
87 | | - WeakSet: WeakSet, |
88 | | - ArrayBuffer: ArrayBuffer, |
89 | | - SharedArrayBuffer: SharedArrayBuffer, |
90 | | - Atomics: Atomics, |
91 | | - DataView: DataView, |
92 | | - Int8Array: Int8Array, |
93 | | - Uint8Array: Uint8Array, |
94 | | - Uint8ClampedArray: Uint8ClampedArray, |
95 | | - Int16Array: Int16Array, |
96 | | - Uint16Array: Uint16Array, |
97 | | - Int32Array: Int32Array, |
98 | | - Uint32Array: Uint32Array, |
99 | | - Float32Array: Float32Array, |
100 | | - Float64Array: Float64Array, |
101 | | - BigInt64Array: BigInt64Array, |
102 | | - BigUint64Array: BigUint64Array, |
103 | | - |
104 | | - // Other necessary globals |
| 70 | + Promise: Promise, |
| 71 | + Math: Math, |
105 | 72 | TextEncoder: global.TextEncoder, |
106 | 73 | TextDecoder: global.TextDecoder, |
107 | 74 | BigInt: global.BigInt, |
108 | | - Symbol: Symbol, |
109 | | - Proxy: Proxy, |
110 | | - Reflect: Reflect, |
111 | | - Object: Object, |
112 | | - Array: Array, |
113 | | - Function: Function, |
114 | | - String: String, |
115 | | - Number: Number, |
116 | | - Boolean: Boolean, |
117 | | - RegExp: RegExp, |
118 | | - Math: Math, |
119 | | - JSON: JSON, |
120 | | - Intl: global.Intl, |
121 | 75 | crypto: global.crypto, |
122 | 76 |
|
123 | 77 | // Custom require that blocks core modules |
124 | 78 | require: createRestrictedRequire(), |
125 | 79 |
|
| 80 | + // Driver require |
| 81 | + __driver_require: require, |
| 82 | + |
126 | 83 | // Needed for some modules |
127 | 84 | global: undefined as any, |
128 | 85 | globalThis: undefined as any |
|
0 commit comments