isolated-function 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -4
- package/src/compile.js +21 -15
- package/src/index.js +27 -21
- package/src/template/index.js +11 -28
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "isolated-function",
|
|
3
3
|
"description": "Runs untrusted code in a Node.js v8 sandbox.",
|
|
4
4
|
"homepage": "https://github.com/Kikobeats/isolated-function",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.4",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js"
|
|
@@ -37,10 +37,8 @@
|
|
|
37
37
|
"acorn-walk": "~8.3.3",
|
|
38
38
|
"ensure-error": "~3.0.1",
|
|
39
39
|
"esbuild": "~0.23.1",
|
|
40
|
-
"process-stats": "~3.7.10",
|
|
41
40
|
"serialize-error": "8",
|
|
42
|
-
"tinyspawn": "~1.3.2"
|
|
43
|
-
"v8-sandbox": "~3.2.12"
|
|
41
|
+
"tinyspawn": "~1.3.2"
|
|
44
42
|
},
|
|
45
43
|
"devDependencies": {
|
|
46
44
|
"@commitlint/cli": "latest",
|
package/src/compile.js
CHANGED
|
@@ -46,31 +46,37 @@ const detectDependencies = code => {
|
|
|
46
46
|
return Array.from(dependencies)
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
await fs.mkdir(
|
|
49
|
+
const getTmp = async content => {
|
|
50
|
+
const cwd = await fs.mkdtemp(path.join(tmpdir(), 'compile-'))
|
|
51
|
+
await fs.mkdir(cwd, { recursive: true })
|
|
52
52
|
|
|
53
|
-
const
|
|
53
|
+
const filepath = path.join(cwd, 'index.js')
|
|
54
|
+
await fs.writeFile(filepath, content)
|
|
54
55
|
|
|
55
|
-
const
|
|
56
|
-
|
|
56
|
+
const cleanup = () => fs.rm(cwd, { recursive: true, force: true })
|
|
57
|
+
return { filepath, cwd, content, cleanup }
|
|
58
|
+
}
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
module.exports = async snippet => {
|
|
61
|
+
const tmp = await getTmp(generateTemplate(snippet))
|
|
62
|
+
const dependencies = detectDependencies(tmp.content)
|
|
63
|
+
await $(packageManager.init, { cwd: tmp.cwd })
|
|
64
|
+
await $(`${packageManager.install} ${dependencies.join(' ')}`, {
|
|
65
|
+
cwd: tmp.cwd
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// return tmp
|
|
61
69
|
|
|
62
70
|
const result = await esbuild.build({
|
|
63
|
-
entryPoints: [
|
|
71
|
+
entryPoints: [tmp.filepath],
|
|
64
72
|
bundle: true,
|
|
73
|
+
// minify: true,
|
|
65
74
|
write: false,
|
|
66
75
|
platform: 'node'
|
|
67
76
|
})
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await fs.rm(tmp, { recursive: true })
|
|
72
|
-
|
|
73
|
-
return bundledCode
|
|
78
|
+
await tmp.cleanup()
|
|
79
|
+
return getTmp(result.outputFiles[0].text)
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
module.exports.detectDependencies = detectDependencies
|
package/src/index.js
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { Sandbox } = require('v8-sandbox')
|
|
4
3
|
const { deserializeError } = require('serialize-error')
|
|
4
|
+
const $ = require('tinyspawn')
|
|
5
5
|
|
|
6
6
|
const compile = require('./compile')
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
class TimeoutError extends Error {
|
|
9
|
+
constructor (message) {
|
|
10
|
+
super(message)
|
|
11
|
+
this.name = 'TimeoutError'
|
|
11
12
|
}
|
|
13
|
+
}
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
debug: true
|
|
17
|
-
})
|
|
18
|
-
const compiling = compile(snippet)
|
|
19
|
-
const initializing = sandbox.initialize()
|
|
15
|
+
module.exports = (snippet, { timeout = 0 } = {}) => {
|
|
16
|
+
if (typeof snippet !== 'function') throw new TypeError('Expected a function')
|
|
17
|
+
const compilePromise = compile(snippet)
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
const fn = async (...args) => {
|
|
20
|
+
try {
|
|
21
|
+
const { filepath } = await compilePromise
|
|
22
|
+
const { stdout } = await $(`node ${filepath} ${JSON.stringify(args)}`, {
|
|
23
|
+
timeout,
|
|
24
|
+
killSignal: 'SIGKILL'
|
|
25
|
+
})
|
|
26
|
+
const { isFulfilled, value } = JSON.parse(stdout)
|
|
27
|
+
if (isFulfilled) return value
|
|
28
|
+
throw deserializeError(value)
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (error.killed) throw new TimeoutError('Execution timed out')
|
|
31
|
+
throw error
|
|
32
|
+
}
|
|
31
33
|
}
|
|
34
|
+
|
|
35
|
+
const cleanup = async () => (await compilePromise).cleanup
|
|
36
|
+
|
|
37
|
+
return [fn, cleanup]
|
|
32
38
|
}
|
package/src/template/index.js
CHANGED
|
@@ -2,37 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
const SERIALIZE_ERROR = require('./serialize-error')
|
|
4
4
|
|
|
5
|
-
const DISALLOW_INTERNALS = [
|
|
6
|
-
'_dispatch',
|
|
7
|
-
'base64ToBuffer',
|
|
8
|
-
'bufferToBase64',
|
|
9
|
-
'define',
|
|
10
|
-
'defineAsync',
|
|
11
|
-
'dispatch',
|
|
12
|
-
'httpRequest',
|
|
13
|
-
'info',
|
|
14
|
-
'setResult'
|
|
15
|
-
]
|
|
16
|
-
|
|
17
5
|
const generateTemplate = snippet => {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
6
|
+
const template = `
|
|
7
|
+
const args = JSON.parse(process.argv[2])
|
|
8
|
+
|
|
9
|
+
;(async () => {
|
|
10
|
+
try {
|
|
11
|
+
const value = await (${snippet.toString()})(...args)
|
|
12
|
+
console.log(JSON.stringify({ isFulfilled: true, value }))
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.log(JSON.stringify({ isFulfilled: false, value: ${SERIALIZE_ERROR}(error) }))
|
|
15
|
+
}
|
|
25
16
|
})()
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
setResult({
|
|
30
|
-
value: ${value}
|
|
31
|
-
})
|
|
32
|
-
} catch(error) {
|
|
33
|
-
setResult({ error: ${SERIALIZE_ERROR}(error) })
|
|
34
|
-
}
|
|
35
|
-
})()`
|
|
18
|
+
`
|
|
36
19
|
|
|
37
20
|
return template
|
|
38
21
|
}
|