[Detail Bug] Sandbox: Dependency whitelist in vmOpts.allow is ignored, allowing imports of any package
# Detail Bug Report
https://app.detail.dev/org_06887db3-bf54-40ab-976d-46c66ab2b840/bugs/bug_7d906711-8afc-44f8-b572-01046edcaed1
# Summary
- **Context**: The `function.js` module executes user code in an isolated sandbox by calling `isolated-function` with security options including permissions and dependency whitelists.
- **Bug**: The code unconditionally overrides the entire `allow` object when passing options to `isolated-function`, discarding any `allow.dependencies` or `allow.permissions` that were provided in `vmOpts`.
- **Actual vs. expected**: When `vmOpts.allow.dependencies` is provided to restrict which npm packages can be imported, this security restriction is silently ignored. Expected behavior is to merge the permissions while preserving the dependencies whitelist.
- **Impact**: This allows untrusted code to import and execute any npm package, bypassing dependency whitelisting intended for security.
# Code with Bug
In `packages/function/src/function.js`:
```javascript
module.exports = async ({
url,
code,
vmOpts,
browserWSEndpoint,
needsNetwork = template.isUsingPage(code),
source = template(code, needsNetwork),
...opts
}) => {
const permissions = needsNetwork && nodeMajor >= 25 ? ['net'] : []
const [fn, teardown] = isolatedFunction(source, {
...vmOpts,
allow: { permissions }, // <-- BUG 🔴 Completely replaces vmOpts.allow, discarding vmOpts.allow.dependencies
throwError: false
})
const result = await fn(url, browserWSEndpoint, opts)
await teardown()
return result
}
```
# Explanation
Because `...vmOpts` is applied first and then `allow: { permissions }` is set afterward, any `vmOpts.allow` object is overwritten. As a result:
- `vmOpts.allow.dependencies` is dropped, so dependency whitelisting is not enforced.
- `vmOpts.allow.permissions` is also replaced, causing unexpected permission behavior.
Evidence: a repro passing `vmOpts.allow.dependencies: ['lodash']` while user code does `require('fs')` succeeds (returns `{ isFulfilled: true, value: 'success' }`) instead of failing with a dependency-not-allowed error.
# Exploit Scenario
An attacker (or any untrusted user code executed by this sandbox) can bypass an intended `vmOpts.allow.dependencies` whitelist and import arbitrary modules/packages (e.g., `fs` or other installed npm packages), even when the caller believes imports are restricted.
# Recommended Fix
Merge `allow` rather than replacing it, preserving `vmOpts.allow.dependencies` and combining permissions:
```javascript
const vmOptsAllow = vmOpts?.allow || {}
const [fn, teardown] = isolatedFunction(source, {
...vmOpts,
allow: {
...vmOptsAllow,
permissions: [
...(vmOptsAllow.permissions || []),
...permissions
]
},
throwError: false
})
```
# History
This bug was introduced in commit a1361409. The commit upgraded the `isolated-function` dependency from v0.1.46 to v0.1.47 (changing `allow` from an array to an object), and updated the call site to `allow: { permissions }` without merging with `vmOpts.allow`, discarding `allow.dependencies`.
关闭于 2026-05-17 0 条评论