javascript.express.security.express-expat-xxe.express-expat-xxe

Author
2,175
Download Count*
License
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-expat-xxe
message: 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:
interfile: true
owasp:
- A04:2017 - XML External Entities (XXE)
- A05:2021 - Security Misconfiguration
cwe:
- "CWE-611: Improper Restriction of XML External Entity Reference"
asvs:
section: V5 Validation, Sanitization and Encoding
control_id: 5.5.2 Insecue XML Deserialization
control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention
version: "4"
references:
- https://github.com/astro/node-expat
category: security
technology:
- express
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
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-either:
- pattern-inside: |
$XML = require('node-expat')
...
- pattern-inside: |
import $XML from 'node-expat'
...
- pattern-inside: |
import * as $XML from 'node-expat'
...
- pattern-either:
- pattern-inside: |
$PARSER = new $XML.Parser(...);
...
- pattern-either:
- pattern: $PARSER.parse($QUERY)
- pattern: $PARSER.write($QUERY)
- focus-metavariable: $QUERY
Examples
express-expat-xxe.js
const express = require('express')
const app = express()
const port = 3000
const expat = require('node-expat');
app.get('/test', async (req, res) => {
var parser = new expat.Parser('UTF-8')
// ruleid: express-expat-xxe
parser.parse(req.body)
res.send('Hello World!')
})
app.get('/test1', async (req, res) => {
var parser = new expat.Parser('UTF-8')
// ruleid: express-expat-xxe
parser.write(req.query.value)
res.send('Hello World!')
})
app.get('/test2', async (req, res) => {
var parser = new expat.Parser('UTF-8')
var data = req.body.foo
// ruleid: express-expat-xxe
parser.write(data)
res.send('Hello World!')
})
const test3 = function func3(req, res) {
var parser = new expat.Parser('UTF-8')
// ruleid: express-expat-xxe
parser.parse(req.body)
res.send('Hello World!')
}
const test4 = function (req, res) {
var parser = new expat.Parser('UTF-8')
// ruleid: express-expat-xxe
parser.parse(req.body)
res.send('Hello World!')
}
app.get('/okTest1', async (req, res) => {
var parser = new expat.Parser('UTF-8')
// ok: express-expat-xxe
parser.write('<xml>hardcoded</xml>')
res.send('Hello World!')
})
app.get('/okTest2', async (req, res) => {
var parser = new expat.Parser('UTF-8')
var data = foo()
// ok: express-expat-xxe
parser.write(data)
res.send('Hello World!')
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
Short Link: https://sg.run/BkXx