javascript.lang.security.audit.sqli.node-knex-sqli.node-knex-sqli
semgrep
Author
unknown
Download Count*
License
Detected SQL statement that is tainted by $REQ
object. This could lead to SQL injection if the variable is user-controlled and not properly sanitized. In order to prevent SQL injection, it is recommended to use parameterized queries or prepared statements. An example of parameterized queries like so: knex.raw('SELECT $1 from table', [userinput])
can help prevent SQLi.
Run Locally
Run in CI
Defintion
rules:
- id: node-knex-sqli
message: "Detected SQL statement that is tainted by `$REQ` object. This could
lead to SQL injection if the variable is user-controlled and not properly
sanitized. In order to prevent SQL injection, it is recommended to use
parameterized queries or prepared statements. An example of parameterized
queries like so: `knex.raw('SELECT $1 from table', [userinput])` can help
prevent SQLi."
metadata:
confidence: MEDIUM
references:
- https://knexjs.org/#Builder-fromRaw
- https://knexjs.org/#Builder-whereRaw
- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
category: security
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
cwe:
- "CWE-89: Improper Neutralization of Special Elements used in an SQL
Command ('SQL Injection')"
technology:
- express
- nodejs
- knex
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
vulnerability_class:
- SQL 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
- 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:
- patterns:
- focus-metavariable: $QUERY
- pattern-either:
- pattern-inside: $KNEX.fromRaw($QUERY, ...)
- pattern-inside: $KNEX.whereRaw($QUERY, ...)
- pattern-inside: $KNEX.raw($QUERY, ...)
- pattern-either:
- pattern-inside: |
require('knex')
...
- pattern-inside: |
import 'knex'
...
pattern-sanitizers:
- patterns:
- pattern: parseInt(...)
Examples
node-knex-sqli.js
import knex from "knex";
import Knex from "knex";
exports.handler = async (req,res,next) => {
const connection = knex({
client: "mysql",
connection: {
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT || "3306"),
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
},
});
// ruleid: node-knex-sqli
await connection.raw(`
INSERT INTO (id, character, cartoon, link)
VALUES(
'${req.query.id}',
'${req.body.character}',
'${req.query.cartoon}',
'${req.foo.link}'
)
`);
// ok: node-knex-sqli
await connection.raw('SELECT * FROM foobar');
};
Short Link: https://sg.run/l9eE