javascript.express.security.audit.remote-property-injection.remote-property-injection

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Bracket object notation with user input is present, this might allow an attacker to access all properties of the object and even it's prototype. Use literal values for object properties.

Run Locally

Run in CI

Defintion

rules:
  - id: remote-property-injection
    message: Bracket object notation with user input is present, this might allow an
      attacker to access all properties of the object and even it's prototype.
      Use literal values for object properties.
    metadata:
      confidence: LOW
      owasp:
        - A02:2017 - Broken Authentication
        - A04:2021 - Insecure Design
      cwe:
        - "CWE-522: Insufficiently Protected Credentials"
      category: security
      technology:
        - express
      references:
        - https://github.com/nodesecurity/eslint-plugin-security/blob/3c7522ca1be800353513282867a1034c795d9eb4/docs/the-dangers-of-square-bracket-notation.md
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cryptographic Issues
    languages:
      - javascript
      - typescript
    severity: ERROR
    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) => {...}
          - focus-metavariable: $REQ
          - pattern-either:
              - pattern: params
              - pattern: query
              - pattern: cookies
              - pattern: headers
              - pattern: body
    pattern-sinks:
      - patterns:
          - pattern-inside: $OBJ[...] = ...
          - pattern-not-inside: $OBJ["..."] = ...
          - pattern-not-inside: $OBJ[...] = "..."
          - pattern: $INDEX
          - pattern-not: |
              "..." + $INDEX
          - pattern-not: |
              $INDEX + "..."
    pattern-sanitizers:
      - patterns:
          - pattern: var $X = ...
          - pattern-not: var $X = $REQ.$ANY

Examples

remote-property-injection.js

var express = require('express');

var app = express();
var myObj = {}

app.get('/test1', function(req, res) {
  var prop = req.query.userControlled
  // ruleid: remote-property-injection
  myObj[prop] = function() {}
  res.send('ok')
})

app.get('/test2', function(req, res) {
  // ruleid: remote-property-injection
  myObj[req.body] = foobar()
  res.send('ok')
})

app.get('/okTest', function(req, res) {
  var prop = "$" + req.query.userControlled
  // ok: remote-property-injection
  myObj[prop] = function() {}
  res.send('ok')
})