javascript.express.security.audit.express-libxml-noent.express-libxml-noent

profile photo of semgrepsemgrep
Author
unknown
Download Count*

The libxml library processes user-input with the noent attribute is set to true which can lead to being vulnerable to XML External Entities (XXE) type attacks. It is recommended to set noent to false when using this feature to ensure you are protected.

Run Locally

Run in CI

Defintion

rules:
  - id: express-libxml-noent
    message: The libxml library processes user-input with the `noent` attribute is
      set to `true` which can lead to being vulnerable to XML External Entities
      (XXE) type attacks. It is recommended to set `noent` to `false` when using
      this feature to ensure you are protected.
    options:
      interfile: true
    metadata:
      interfile: true
      references:
        - https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
      technology:
        - express
      category: security
      cwe:
        - "CWE-611: Improper Restriction of XML External Entity Reference"
      owasp:
        - A04:2017 - XML External Entities (XXE)
        - A05:2021 - Security Misconfiguration
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: HIGH
      impact: HIGH
      confidence: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - XML Injection
    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
              - pattern: $REQ.files.$ANYTHING.data.toString('utf8')
              - pattern: $REQ.files.$ANYTHING['data'].toString('utf8')
      - 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: files.$ANYTHING.data.toString('utf8')
              - pattern: files.$ANYTHING['data'].toString('utf8')
    pattern-sinks:
      - pattern-either:
          - patterns:
              - pattern-either:
                  - pattern-inside: |
                      $XML = require('$IMPORT')
                      ...
                  - pattern-inside: |
                      import $XML from '$IMPORT'
                        ...
                  - pattern-inside: |
                      import * as $XML from '$IMPORT'
                      ...
              - metavariable-regex:
                  metavariable: $IMPORT
                  regex: ^(libxmljs|libxmljs2)$
              - pattern-inside: $XML.$FUNC($QUERY, {...,noent:true,...})
              - metavariable-regex:
                  metavariable: $FUNC
                  regex: ^(parseXmlString|parseXml)$
              - focus-metavariable: $QUERY

Examples

express-libxml-noent.js

var libxmljs = require("libxmljs");
var libxmljs2 = require("libxmljs2");

module.exports.foo =  function(req, res) {

	// ruleid: express-libxml-noent
	libxmljs.parseXmlString(req.files.products.data.toString('utf8'), {noent:true,noblanks:true})
	// ruleid: express-libxml-noent
	libxmljs.parseXml(req.query.products, {noent:true,noblanks:true})
	// ok: express-libxml-noent
	libxmljs.parseXml(req.files.products.data.toString('utf8'), {noent:false,noblanks:true})
	// ruleid: express-libxml-noent
	libxmljs2.parseXmlString(req.body, {noent:true,noblanks:true})
	// ruleid: express-libxml-noent
	libxmljs2.parseXml(req.body, {noent:true,noblanks:true})
	// ok: express-libxml-noent
	libxmljs2.parseXml(req.body, {noent:false,noblanks:true})
}