contrib.nodejsscan.eval_node.eval_nodejs

profile photo of returntocorpreturntocorp
Author
99
Download Count*
License

User controlled data was found to enter a dynamic execution of JavaScript. This can lead to Remote Code Injection. Where possible do not dynamically execute user-input in functions such as eval(...).

Run Locally

Run in CI

Defintion

rules:
  - id: eval_nodejs
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-either:
              - pattern-inside: function ... ($REQ, $RES) {...}
              - pattern-inside: function ... ($REQ, $RES, $NEXT) {...}
              - patterns:
                  - pattern-either:
                      - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...})
                      - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...})
                  - metavariable-regex:
                      metavariable: $METHOD
                      regex: ^(get|post|put|head|delete|options)$
          - pattern-either:
              - pattern: $REQ.query
              - pattern: $REQ.body
              - pattern: $REQ.params
              - pattern: $REQ.cookies
              - pattern: $REQ.headers
      - patterns:
          - pattern-either:
              - pattern-inside: |
                  ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) =>
                  {...}
              - pattern-inside: |
                  ({ $REQ }: Request,$RES: Response) => {...}
          - pattern-either:
              - pattern: params
              - pattern: query
              - pattern: cookies
              - pattern: headers
              - pattern: body
    pattern-sinks:
      - patterns:
          - pattern-either:
              - pattern: |
                  new Function(...,<... $SINK ...>)
              - pattern: |
                  new Function(<... $SINK ...>)(...)
              - pattern: |
                  eval(<... $SINK ...>)
              - pattern: |
                  setTimeout( <... $SINK ...>, ...)
              - pattern: |
                  setInterval(<... $SINK ...>, ...)
          - focus-metavariable: $SINK
    message: User controlled data was found to enter a dynamic execution of
      JavaScript. This can lead to Remote Code Injection. Where possible do not
      dynamically execute user-input in functions such as eval(...).
    languages:
      - javascript
    severity: ERROR
    metadata:
      references:
        - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!
      owasp:
        - A03:2021 - Injection
        - A01:2017 - Injection
      cwe: "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated
        Code ('Eval Injection')"
      category: security
      technology:
        - node.js
        - express
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]

Examples

eval_node.js

var express = require('express');
var app = express();
app.get('/', function (req, res) {
    // ruleid:eval_nodejs
    var resp = eval("(" + req.query.name + ")");
    // ruleid:eval_nodejs
    var z = new Function('arg1', 'arg2', req.query.name)
    z(1, 2);
    // ruleid:eval_nodejs
    setTimeout('alert(' + req.body.name, 0);
    // ruleid:eval_nodejs
    setInterval(req.body.name, 0);
    res.send('Response</br>');
});
app.listen(8000);
// ok:eval_nodejs
eval("outside_express" + req.foo)
// ok:eval_nodejs
setTimeout('alert(' + req.body.name, 0);
// ok:eval_nodejs
setInterval(req.body.name, 0);
// ok:eval_nodejs
new Function('arg1', 'arg2', req.query.name)