Skip to content

Commit e3dbdc3

Browse files
committed
add custom query builder and active record querybuilder support
1 parent 242f7e1 commit e3dbdc3

File tree

3 files changed

+160
-153
lines changed

3 files changed

+160
-153
lines changed

javascript/ql/lib/semmle/javascript/frameworks/TypeORM.qll

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,31 @@ import javascript
55
*/
66
module TypeOrm {
77
/**
8-
* Gets an expression that constructs or returns a TypeORM database instance.
8+
* Gets a `DataSource` instance
99
*/
1010
API::Node dataSource() {
1111
result = API::moduleImport("typeorm").getMember("DataSource").getInstance()
1212
}
1313

1414
/**
15-
* Gets an `QueryRunner`
15+
* Gets a `QueryRunner` nodes
1616
*/
1717
API::Node queryRunner() { result = dataSource().getMember("createQueryRunner").getReturn() }
1818

1919
/**
20-
* Gets `createQueryBuilder` return value from a Active record based Entity
20+
* Gets a `*QueryBuilder` node of an Active record based Entity
2121
*/
2222
API::Node activeRecordQueryBuilder() {
23-
result = queryRunner().getMember("manager").getMember("createQueryBuilder").getReceiver()
23+
result =
24+
API::moduleImport("typeorm")
25+
.getMember("Entity")
26+
.getReturn()
27+
.getADecoratedClass()
28+
.getMember("createQueryBuilder")
2429
}
2530

2631
/**
27-
* Gets `createQueryBuilder` return value from a Data Mapper based Entity
32+
* Gets a `*QueryBuilder` node of a Data Mapper based Entity
2833
*/
2934
API::Node dataMapperQueryBuilder() {
3035
result =
@@ -36,10 +41,19 @@ module TypeOrm {
3641
// Using entity manager
3742
dataSource().getMember("manager"), queryRunner().getMember("manager")
3843
].getMember("createQueryBuilder").getReturn()
44+
or
45+
// in case of custom query builders
46+
result =
47+
API::moduleImport("typeorm")
48+
.getMember([
49+
"SelectQueryBuilder", "InsertQueryBuilder", "RelationQueryBuilder",
50+
"UpdateQueryBuilder"
51+
])
52+
.getInstance()
3953
}
4054

4155
/**
42-
* Gets return value of a `createQueryBuilder`
56+
* Gets a `*QueryBuilder` node
4357
*/
4458
API::Node queryBuilderInstance() {
4559
result = dataMapperQueryBuilder() or
@@ -91,8 +105,8 @@ module TypeOrm {
91105
string selectExpression() {
92106
result =
93107
[
94-
"select", "addSelect", "from", "where", "andWhere", "orWhere", "having", "orHaving",
95-
"andHaving", "orderBy", "addOrderBy", "distinctOn", "groupBy", "addCommonTableExpression",
108+
"select", "addSelect", "where", "andWhere", "orWhere", "having", "orHaving", "andHaving",
109+
"orderBy", "addOrderBy", "distinctOn", "groupBy", "addCommonTableExpression",
96110
"leftJoinAndSelect", "innerJoinAndSelect", "leftJoin", "innerJoin", "leftJoinAndMapOne",
97111
"innerJoinAndMapOne", "leftJoinAndMapMany", "innerJoinAndMapMany", "orUpdate", "orIgnore",
98112
"values", "set"
@@ -116,8 +130,8 @@ module TypeOrm {
116130
typeOrmNode = getASuccessorOfBuilderInstance() and
117131
this = typeOrmNode.asSource()
118132
or
119-
// I'm doing following because this = TypeORMNode.asSource()s
120-
// won't let me to get a member in getAQueryArgument
133+
// I'm doing following because `this = TypeORMNode.asSource()`
134+
// don't let me to get a member in getAQueryArgument
121135
typeOrmNode = getASuccessorOfBrackets() and
122136
typeOrmNode.getMember(selectExpression()).getACall() = this
123137
}
@@ -137,7 +151,7 @@ module TypeOrm {
137151
or
138152
memberName =
139153
[
140-
"select", "addSelect", "from", "where", "andWhere", "orWhere", "having", "orHaving",
154+
"select", "addSelect", "where", "andWhere", "orWhere", "having", "orHaving",
141155
"andHaving", "orderBy", "addOrderBy", "distinctOn", "groupBy",
142156
"addCommonTableExpression"
143157
] and
@@ -167,8 +181,8 @@ module TypeOrm {
167181
/** An expression that is passed to the `query` function and hence interpreted as SQL. */
168182
class QueryString extends SQL::SqlString {
169183
QueryString() {
170-
this = any(QueryRunner qc).getAQueryArgument() or
171-
this = any(QueryBuilderCall qc).getAQueryArgument()
184+
this = any(QueryRunner qr).getAQueryArgument() or
185+
this = any(QueryBuilderCall qb).getAQueryArgument()
172186
}
173187
}
174188
}
Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,40 @@
1-
| test.ts:70:17:70:27 | "user.name" |
2-
| test.ts:71:16:71:46 | "user.r ... stered" |
3-
| test.ts:80:29:80:46 | "Vulnerable \\")--" |
4-
| test.ts:85:13:85:57 | ["first ... --\\" "] |
5-
| test.ts:86:13:86:37 | ["exter ... ")-- "] |
6-
| test.ts:93:33:93:50 | "Vulnerable \\")--" |
7-
| test.ts:94:16:94:49 | "user2. ... OR 1=1" |
8-
| test.ts:100:15:100:19 | User2 |
9-
| test.ts:101:16:101:30 | "id = 1 OR 1=1" |
10-
| test.ts:107:53:107:73 | "select ... USER2" |
11-
| test.ts:112:17:112:19 | "*" |
12-
| test.ts:113:16:113:28 | "user.id >=3" |
13-
| test.ts:121:47:121:68 | "User.i ... OR 1=1" |
14-
| test.ts:127:66:127:87 | "User.i ... OR 1=1" |
15-
| test.ts:134:16:142:9 | (qb) => ... } |
16-
| test.ts:137:25:137:41 | "User2.firstName" |
17-
| test.ts:138:23:138:27 | User2 |
18-
| test.ts:139:24:139:47 | "user2. ... stered" |
19-
| test.ts:150:93:150:109 | "User2.id =:kind" |
20-
| test.ts:152:92:152:120 | "User2. ... OR 1=1" |
21-
| test.ts:159:17:159:23 | "User2" |
22-
| test.ts:160:15:160:19 | User2 |
23-
| test.ts:161:16:161:31 | "User2.id = :id" |
24-
| test.ts:167:51:167:79 | "User2. ... OR 1=1" |
25-
| test.ts:171:53:171:62 | "User2.id" |
26-
| test.ts:171:72:171:101 | "User2. ... stName" |
27-
| test.ts:176:52:176:81 | "photo. ... emoved" |
28-
| test.ts:182:53:182:62 | "User2.id" |
29-
| test.ts:182:72:182:101 | "User2. ... stName" |
30-
| test.ts:188:51:188:80 | "User2. ... stName" |
31-
| test.ts:192:13:196:14 | new Bra ... }) |
32-
| test.ts:193:26:193:55 | "User2. ... stName" |
33-
| test.ts:195:28:195:73 | "User2. ... R (1=1" |
34-
| test.ts:198:18:198:27 | "User2.id" |
35-
| test.ts:198:38:198:43 | "id=1" |
36-
| test.ts:204:25:204:29 | "1=1" |
37-
| test.ts:210:16:210:32 | "User2.id =:kind" |
38-
| test.ts:212:13:216:14 | new Bra ... }) |
39-
| test.ts:213:26:213:55 | "User2. ... stName" |
40-
| test.ts:215:28:215:73 | "User2. ... R (1=1" |
41-
| test.ts:218:13:222:14 | new Not ... }) |
42-
| test.ts:219:26:219:55 | "User2. ... stName" |
43-
| test.ts:221:28:221:55 | "User2. ... stName" |
1+
| test.ts:19:20:19:50 | "user.f ... rstName |
2+
| test.ts:20:23:20:51 | "user.l ... astName |
3+
| test.ts:83:30:83:37 | BadInput |
4+
| test.ts:89:31:89:38 | BadInput |
5+
| test.ts:98:29:98:36 | BadInput |
6+
| test.ts:112:29:112:36 | BadInput |
7+
| test.ts:116:13:116:32 | [BadInput, BadInput] |
8+
| test.ts:117:13:117:22 | [BadInput] |
9+
| test.ts:123:32:123:39 | BadInput |
10+
| test.ts:124:16:124:23 | BadInput |
11+
| test.ts:130:16:130:23 | BadInput |
12+
| test.ts:135:29:135:36 | BadInput |
13+
| test.ts:139:17:139:24 | BadInput |
14+
| test.ts:140:16:140:23 | BadInput |
15+
| test.ts:144:47:144:54 | BadInput |
16+
| test.ts:150:66:150:73 | BadInput |
17+
| test.ts:157:16:165:9 | (qb) => ... } |
18+
| test.ts:160:25:160:32 | BadInput |
19+
| test.ts:162:24:162:31 | BadInput |
20+
| test.ts:171:92:171:119 | "User2. ... adInput |
21+
| test.ts:176:17:176:23 | "User2" |
22+
| test.ts:178:16:178:23 | BadInput |
23+
| test.ts:183:51:183:78 | "User2. ... adInput |
24+
| test.ts:186:52:186:59 | BadInput |
25+
| test.ts:188:53:188:62 | "User2.id" |
26+
| test.ts:188:72:188:79 | BadInput |
27+
| test.ts:192:51:192:58 | BadInput |
28+
| test.ts:196:13:198:14 | new Bra ... }) |
29+
| test.ts:197:26:197:33 | BadInput |
30+
| test.ts:197:44:197:51 | BadInput |
31+
| test.ts:200:18:200:25 | BadInput |
32+
| test.ts:200:36:200:43 | BadInput |
33+
| test.ts:205:25:205:32 | BadInput |
34+
| test.ts:211:16:211:23 | BadInput |
35+
| test.ts:213:13:215:14 | new Bra ... }) |
36+
| test.ts:214:26:214:33 | BadInput |
37+
| test.ts:214:44:214:51 | BadInput |
38+
| test.ts:217:13:219:14 | new Not ... }) |
39+
| test.ts:218:26:218:33 | BadInput |
40+
| test.ts:218:44:218:51 | BadInput |

0 commit comments

Comments
 (0)