Skip to content

Commit 35f294f

Browse files
committed
JS: Improve sequelize model
1 parent 93500bd commit 35f294f

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

javascript/ql/src/semmle/javascript/frameworks/SQL.qll

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -463,22 +463,34 @@ private module MsSql {
463463
* Provides classes modelling the `sequelize` package.
464464
*/
465465
private module Sequelize {
466-
/** Gets an import of the `sequelize` module. */
467-
API::Node sequelize() { result = API::moduleImport("sequelize") }
466+
/** Gets an import of the `sequelize` module or one that re-exports it. */
467+
API::Node sequelize() { result = API::moduleImport(["sequelize", "sequelize-typescript"]) }
468468

469469
/** Gets an expression that creates an instance of the `Sequelize` class. */
470-
API::Node newSequelize() { result = sequelize().getInstance() }
470+
API::Node instance() {
471+
result = [sequelize(), sequelize().getMember("Sequelize")].getInstance()
472+
or
473+
result = API::Node::ofType(["sequelize", "sequelize-typescript"], ["Sequelize", "default"])
474+
}
471475

472476
/** A call to `Sequelize.query`. */
473477
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
474-
QueryCall() { this = newSequelize().getMember("query").getACall() }
478+
QueryCall() { this = instance().getMember("query").getACall() }
475479

476-
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
480+
override DataFlow::Node getAQueryArgument() {
481+
result = getArgument(0)
482+
or
483+
result = getOptionArgument(0, "query")
484+
}
477485
}
478486

479487
/** An expression that is passed to `Sequelize.query` method and hence interpreted as SQL. */
480488
class QueryString extends SQL::SqlString {
481-
QueryString() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
489+
QueryString() {
490+
this = any(QueryCall qc).getAQueryArgument().asExpr()
491+
or
492+
this = sequelize().getMember(["literal", "asIs"]).getParameter(0).getARhs().asExpr()
493+
}
482494
}
483495

484496
/**

javascript/ql/test/library-tests/frameworks/SQL/SqlString.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
| postgres-types.ts:4:18:4:29 | 'SELECT 123' |
3434
| postgresImport.js:4:18:4:43 | 'SELECT ... number' |
3535
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
36+
| sequelize2.js:12:17:15:1 | {\\n que ... [123]\\n} |
37+
| sequelize2.js:13:10:13:20 | 'SELECT $1' |
38+
| sequelize2.js:17:31:17:41 | '123 + 345' |
39+
| sequelize-types.ts:7:24:7:35 | 'SELECT 123' |
3640
| sequelize.js:8:17:8:118 | 'SELECT ... Y name' |
3741
| sequelizeImport.js:3:17:3:118 | 'SELECT ... Y name' |
3842
| spanner2.js:5:26:5:35 | "SQL code" |
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Sequelize from 'sequelize';
2+
3+
export class Foo {
4+
constructor(private seq: Sequelize) {}
5+
6+
method() {
7+
this.seq.query('SELECT 123');
8+
}
9+
}

javascript/ql/test/library-tests/frameworks/SQL/sequelize2.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ const sequelize = new Sequelize('database', {
99
});
1010
sequelize.query('SELECT * FROM Products WHERE (name LIKE \'%' + criteria + '%\') AND deletedAt IS NULL) ORDER BY name');
1111

12+
sequelize.query({
13+
query: 'SELECT $1',
14+
values: [123]
15+
});
16+
17+
let value = Sequelize.literal('123 + 345');

0 commit comments

Comments
 (0)