javascript.express.security.express-vm2-injection.express-vm2-context-injection

Author
5,905
Download Count*
License
Make sure that unverified user data can not reach vm2
.
Run Locally
Run in CI
Defintion
rules:
- id: express-vm2-context-injection
message: |
Make sure that unverified user data can not reach `vm2`.
severity: ERROR
languages:
- javascript
- typescript
metadata:
owasp: "A1: Injection"
cwe: "CWE-94: Improper Control of Generation of Code (Code Injection)"
category: security
technology:
- express
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
patterns:
- pattern-inside: |
require('vm2');
...
- pattern-either:
- pattern-inside: function ... ($REQ, $RES) {...}
- pattern-inside: function ... ($REQ, $RES, $NEXT) {...}
- pattern-inside: $APP.get(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.post(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.put(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.head(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.delete(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.options(..., function $FUNC($REQ, $RES) {...})
- pattern-either:
- pattern: |
new VM({sandbox: <... $REQ.$QUERY.$FOO ...>},...);
- pattern: |
$CONTEXT = <... $REQ.$QUERY.$FOO ...>;
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>;
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>};
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$VAR = <... $REQ.$QUERY.$FOO ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$OPTS = {sandbox: <... $REQ.$QUERY.$FOO ...>};
...
new VM($OPTS,...);
- pattern: |
$CONTEXT = <... $REQ.$QUERY.$FOO ...>;
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new VM($OPTS,...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new VM($OPTS,...);
- pattern: |
$VAR = <... $REQ.$QUERY.$FOO ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new VM($OPTS,...);
- pattern: |
new NodeVM({sandbox: <... $REQ.$QUERY.$FOO ...>},...);
- pattern: |
$CONTEXT = <... $REQ.$QUERY.$FOO ...>;
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = <... {$NAME:$REQ.$QUERY.$FOO} ...>;
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>};
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$VAR = <... $REQ.$QUERY.$FOO ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$OPTS = {sandbox: <... $REQ.$QUERY.$FOO ...>};
...
new NodeVM($OPTS,...);
- pattern: |
$CONTEXT = <... $REQ.$QUERY.$FOO ...>;
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new NodeVM($OPTS,...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$QUERY.$FOO ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new NodeVM($OPTS,...);
- pattern: |
$VAR = <... $REQ.$QUERY.$FOO ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new NodeVM($OPTS,...);
- pattern: |
new VM({sandbox: <... $REQ.$BODY ...>},...);
- pattern: |
$CONTEXT = <... $REQ.$BODY ...>;
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = <... {$NAME:$REQ.$BODY} ...>;
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$BODY ...>};
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$VAR = <... $REQ.$BODY ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
new VM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$OPTS = {sandbox: <... $REQ.$BODY ...>};
...
new VM($OPTS,...);
- pattern: |
$CONTEXT = <... $REQ.$BODY ...>;
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new VM($OPTS,...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$BODY ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new VM($OPTS,...);
- pattern: |
$VAR = <... $REQ.$BODY ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new VM($OPTS,...);
- pattern: |
new NodeVM({sandbox: <... $REQ.$BODY ...>},...);
- pattern: |
$CONTEXT = <... $REQ.$BODY ...>;
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = <... {$NAME:$REQ.$BODY} ...>;
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$BODY ...>};
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$VAR = <... $REQ.$BODY ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
new NodeVM({sandbox: <... $CONTEXT ...>},...);
- pattern: |
$OPTS = {sandbox: <... $REQ.$BODY ...>};
...
new NodeVM($OPTS,...);
- pattern: |
$CONTEXT = <... $REQ.$BODY ...>;
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new NodeVM($OPTS,...);
- pattern: |
$CONTEXT = {$NAME: <... $REQ.$BODY ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new NodeVM($OPTS,...);
- pattern: |-
$VAR = <... $REQ.$BODY ...>;
...
$CONTEXT = {$NAME: <... $VAR ...>};
...
$OPTS = {sandbox: <... $CONTEXT ...>};
...
new NodeVM($OPTS,...);
Examples
express-vm2-injection.js
const fs = require('fs');
const {VM, NodeVM} = require('vm2');
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))
app.get('/test1', (req, res) => {
// ruleid:express-vm2-code-injection
code = `
console.log(${req.query.input})
`;
const sandbox = {
setTimeout,
fs: {
watch: fs.watch
}
};
new VM({
timeout: 40 * 1000,
sandbox
}).run(code);
res.send('hello world');
})
app.get('/test2', function (req, res) {
const sandbox = {
setTimeout,
fs: {
watch: fs.watch
}
};
// ruleid:express-vm2-code-injection
const nodeVM = new NodeVM({timeout: 40 * 1000, sandbox});
nodeVM.run('console.log(' + req.query.input + ')')
res.send('hello world');
})
app.get('/test3', function (req, res) {
const sandbox = {
setTimeout,
fs: {
watch: fs.watch
}
};
// ruleid:express-vm2-code-injection
const nodeVM = new NodeVM({timeout: 40 * 1000, sandbox});
const script = new VMScript(`console.log(${req.query.input})`)
nodeVM.run(script)
res.send('hello world')
})
app.get('/ok-test1', async function (req, res) {
code = `
console.log("Hello world")
`;
const sandbox = {
setTimeout,
fs: {
watch: fs.watch
}
};
const vmResult = new VM({
timeout: 40 * 1000,
sandbox
}).run(code);
res.send('hello world');
})
app.get('/ok-test2', function (req, res) {
const sandbox = {
setTimeout,
fs: {
watch: fs.watch
}
};
const nodeVM = new NodeVM({timeout: 40 * 1000, sandbox});
nodeVM.run('console.log("Hello world")')
res.send('hello world');
})
app.get('/ok-test3', function (req, res) {
const sandbox = {
setTimeout,
fs: {
watch: fs.watch
}
};
const nodeVM = new NodeVM({timeout: 40 * 1000, sandbox});
const script = new VMScript('console.log("Hello world")')
nodeVM.run(script)
res.send('hello world');
})
app.get('/test4', async function test1(req, res) {
code = `
console.log("Hello world")
`;
// ruleid:express-vm2-context-injection
const sandbox = {
setTimeout,
watch: req.query.input
};
return new VM({timeout: 40 * 1000, sandbox}).run(code);
})
app.post('/test5', function test2(req, res) {
// ruleid:express-vm2-context-injection
const sandbox = {
setTimeout,
input: req.body
};
const nodeVM = new NodeVM({timeout: 40 * 1000, sandbox});
return nodeVM.run('console.log("Hello world")')
})
// ok:express-vm2-context-injection
app.get('/ok-test4', async function okTest1() {
code = `
console.log("Hello world")
`;
const sandbox = {
setTimeout,
fs
};
return new VM({timeout: 40 * 1000, sandbox}).run(code);
})
// ok:express-vm2-context-injection
app.get('/ok-test5', function okTest2() {
const sandbox = {
setTimeout,
fs
};
const nodeVM = new NodeVM({timeout: 40 * 1000, sandbox});
return nodeVM.run('console.log("Hello world")')
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
Short Link: https://sg.run/zvDl