javascript.express.security.audit.express-xml2json-xxe-event.express-xml2json-xxe-event

profile photo of semgrepsemgrep
Author
3,077
Download Count*

Xml Parser is used inside Request Event. Make sure that unverified user data can not reach the XML Parser, as it can result in XML External or Internal Entity (XXE) Processing vulnerabilities

Run Locally

Run in CI

Defintion

rules:
  - id: express-xml2json-xxe-event
    message: Xml Parser is used inside Request Event. Make sure that unverified user
      data can not reach the XML Parser, as it can result in XML External or
      Internal Entity (XXE) Processing vulnerabilities
    metadata:
      owasp:
        - A04:2017 - XML External Entities (XXE)
        - A05:2021 - Security Misconfiguration
      cwe:
        - "CWE-611: Improper Restriction of XML External Entity Reference"
      category: security
      technology:
        - express
      references:
        - https://www.npmjs.com/package/xml2json
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: HIGH
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - XML Injection
    languages:
      - javascript
      - typescript
    severity: WARNING
    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-either:
              - pattern-inside: |
                  require('xml2json');
                  ...
              - pattern-inside: |
                  import 'xml2json';
                  ...
          - pattern: $REQ.on('...', function(...) { ... $EXPAT.toJson($INPUT,...); ... })

Examples

express-xml2json-xxe-event.js

const expat = require('xml2json');

function test1() {
    var winston = require('winston'),
        express = require('express');

    var xmlParsingMiddleware = function(req, res, next) {
        var buf = '';
        req.setEncoding('utf8');
        req.on('data', function (chunk) {
            buf += chunk
        });
        // ruleid: express-xml2json-xxe-event
        req.on('end', function () {
            req.body = expat.toJson(buf, {coerce: true, object: true});
            next();
        });
    };
}

function test2() {
    const express = require('express')
    const app = express()
    const port = 3000

    app.get('/', (req, res) => {
        var buf = '';
        req.setEncoding('utf8');
        req.on('data', function (chunk) {
            buf += chunk
        });
        // ruleid: express-xml2json-xxe-event
        req.on('end', function () {
            req.body = expat.toJson(buf, {coerce: true, object: true});
            next();
        });
    })

    app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
}

function okTest() {
    const express = require('express')
    const app = express()
    const port = 3000
    const someEvent = require('some-event')

    // ok: express-xml2json-xxe-event
    someEvent.on('event', function (err, data) {
        req.body = expat.toJson(data, {coerce: true, object: true});
        next();
    });

    app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
}