Jailed Function
Jailed Function is a Node.js library that safely runs untrusted code. It can be used in cloud services or low-code platforms that need to execute user-provided JavaScript.
Features
- Immune to all known attacks: Jailed Function uses a variety of security mechanisms to prevent attacks, including code contrains, sandboxing, and runtime watchdog.
- Securely run JavaScript code: Jailed Function allows you to run untrusted JavaScript code in a safe environment. Your code and the jailed code will share the same event loop, but the jailed code will be unable to access your data or resources.
- Customizable function execution time limit: You can set a limit on the amount of time that a jailed function can execute. This helps to prevent DoS attacks and other malicious behavior.
- Customizable function memory allocation: You can set a limit on the amount of memory that a jailed function can allocate. This helps to prevent memory leaks and other resource-intensive behavior.
How does it work
- The source code is transpiled to a secure source code by allowing only a JavaScript subset and limiting global variable access at compile time. Additionaly the new code contains runtime memory and execution time checks to limit resource usage on each run.
- Run secured source code in an isolated context using Node.js VM.
- All imported globals, arguments passed, and return values of jailed functions are made read-only using Proxies, thus preventing mutations.
Usage
Basic usage:
const jailedFunc = createJailedFunction({
source: `async (num1, num2) => {
return num1 + num2
}`
})
await jailedFunc([2, 3]) // returns 5
Injecting global variables into the execution context:
const finUserById = createJailedFunction({
// declaring global vars
globalNames: ['userService']
source: `async (id) => {
return userService.byId(id)
}`
})
// execute the function providing global vars
await finUserById([1], { userService })
Options
-
globalNames
List of global variable names allowed to use inside the jailed function. -
timeout (ms)
Maximum execution time for the function. Default 1min. -
syncTimeout (ms)
Maximum execution time for the function running synchronous code. Default 100ms. -
memoryLimit (bytes)
Maximum amount of memory that the function is allowed to allocate. -
source
The function source code. This function must beasync
. -
filename
The filename to display in the stack trace. -
readOnlyResult
Whether to make read-only jailed function return value. Defaulttrue
. -
readOnlyGlobals
Whether to make read-only jailed function globals. Defaulttrue
. -
readOnlyArguments
Whether to make read-only jailed function arguments. Defaulttrue
.
Globals
Jailed Function provides access to several convenient built-in globals.
-
console [log, error, warn]
muted in production Object [keys, values, hasOwnProperty, fromEntries, assign, create]
Promise [all, race, resolve, reject, allSettled]
Date [now, parse, UTC]
Array [isArray, from, of]
Number [isFinite, isInteger, isNaN, isSafeInteger, parseFloat, parseInt, MAX_VALUE, MIN_VALUE, NaN, NEGATIVE_INFINITY, POSITIVE_INFINITY, MAX_SAFE_INTEGER, MIN_SAFE_INTEGER, EPSILON]
String [romCharCode, fromCodePoint, raw]
Util
-
readOnly(target: any, traps: {})
Prevents object modification. -
createGetTrap(propNames: string[])
Create Proxy get traps that allow access only to the properties passed in arguments.
Inject Math
object allowing only max
property access.
const max = createJailedFunction({
// declare injected global
globalNames: ['Math']
source: `async (a, b) => Math.max(a, b)`
})
// execute the function providing global vars
await max([1], { Math: readOnly(Math, createGetTrap(['max'])) })
(c) 2023-present Yosbel Marín, MIT License