mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
move TypeORM library file and tests to experimental
add inline tests :) Fix TypeORM fuzzy method according to Review
This commit is contained in:
220
javascript/ql/test/experimental/TypeOrm/test.ts
Normal file
220
javascript/ql/test/experimental/TypeOrm/test.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import {
|
||||
BaseEntity, Brackets, DataSource, JoinColumn, NotBrackets
|
||||
, OneToOne, Entity, PrimaryGeneratedColumn, Column, SelectQueryBuilder, InsertQueryBuilder
|
||||
} from "typeorm";
|
||||
|
||||
@Entity()
|
||||
export class UserActiveRecord extends BaseEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
firstName: string
|
||||
@Column()
|
||||
lastName: string
|
||||
@Column()
|
||||
age: number
|
||||
|
||||
static findByName(firstName: string, lastName: string) {
|
||||
return this.createQueryBuilder("user")
|
||||
.where("user.firstName = " + firstName) // test: SQLInjectionPoint
|
||||
.andWhere("user.lastName = " + lastName) // test: SQLInjectionPoint
|
||||
.getMany()
|
||||
}
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class Profile {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
gender: string
|
||||
@Column()
|
||||
photo: string
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
name: string
|
||||
@OneToOne(() => Profile)
|
||||
@JoinColumn()
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User2 {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
firstName: string
|
||||
@Column()
|
||||
lastName: string
|
||||
@Column()
|
||||
age: number
|
||||
|
||||
}
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: "sqlite",
|
||||
database: "database.sqlite",
|
||||
synchronize: true,
|
||||
logging: false,
|
||||
entities: [User, User2, Profile, UserActiveRecord],
|
||||
migrations: [],
|
||||
subscribers: [],
|
||||
})
|
||||
|
||||
function makePaginationQuery<T>(q: SelectQueryBuilder<T>): SelectQueryBuilder<T> {
|
||||
return q;
|
||||
}
|
||||
|
||||
AppDataSource.initialize().then(async () => {
|
||||
const BadInput = "A user controllable Remote Source like `' 1=1 --` "
|
||||
|
||||
// Active record
|
||||
await UserActiveRecord.findByName(BadInput, "Saw")
|
||||
|
||||
// data mapper
|
||||
const selectQueryBuilder = makePaginationQuery<User>(AppDataSource
|
||||
.createQueryBuilder(User, "User").select());
|
||||
selectQueryBuilder.where(BadInput).getMany().then(result => { // test: SQLInjectionPoint
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
const selectQueryBuilder2 = makePaginationQuery<User>(AppDataSource
|
||||
.createQueryBuilder(User, "User"));
|
||||
selectQueryBuilder2.where(BadInput).getMany().then(result => { // test: SQLInjectionPoint
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
const insertQueryBuilder: InsertQueryBuilder<User2> = AppDataSource
|
||||
.createQueryBuilder(User2, "User2").insert();
|
||||
insertQueryBuilder.into(User2)
|
||||
.values({
|
||||
firstName: "Timber",
|
||||
lastName: () => BadInput, // test: SQLInjectionPoint
|
||||
age: 33,
|
||||
}).execute().then(result => {
|
||||
console.log(result)
|
||||
|
||||
|
||||
})
|
||||
|
||||
AppDataSource
|
||||
.createQueryBuilder(User2, "User")
|
||||
.insert()
|
||||
.into(User2)
|
||||
.values({
|
||||
firstName: "Timber",
|
||||
lastName: () => BadInput, // test: SQLInjectionPoint
|
||||
age: 33,
|
||||
})
|
||||
.orUpdate(
|
||||
[BadInput, BadInput], // test: SQLInjectionPoint
|
||||
[BadInput], // test: SQLInjectionPoint
|
||||
)
|
||||
.getQueryAndParameters()
|
||||
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder("user2")
|
||||
.update(User2)
|
||||
.set({ firstName: () => BadInput, lastName: "Saw2", age: 12 }) // test: SQLInjectionPoint
|
||||
.where(BadInput,) // test: SQLInjectionPoint
|
||||
.execute()
|
||||
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder('user2')
|
||||
.delete()
|
||||
.from(User2)
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.execute()
|
||||
|
||||
|
||||
const queryRunner = AppDataSource.createQueryRunner()
|
||||
await queryRunner.query(BadInput) // test: SQLInjectionPoint
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder(User2, "User")
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.where(BadInput).execute() // test: SQLInjectionPoint
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User, "User")
|
||||
.innerJoin("User.profile", "profile", BadInput, { // test: SQLInjectionPoint
|
||||
id: 2,
|
||||
}).getMany().then(res => console.log(res))
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User, "User")
|
||||
.leftJoinAndMapOne("User.profile", "profile", "profile", BadInput, { // test: SQLInjectionPoint
|
||||
id: 2,
|
||||
}).getMany().then(res => console.log(res))
|
||||
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2")
|
||||
.where((qb) => {
|
||||
const subQuery = qb
|
||||
.subQuery()
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.from(User2, "user2")
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.getQuery()
|
||||
return "User2.id IN " + subQuery
|
||||
})
|
||||
.setParameter("registered", true)
|
||||
.getMany()
|
||||
|
||||
|
||||
// Using repository
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder("User2").where("User2.id =:kind" + BadInput, { kind: 1 }).getMany()
|
||||
|
||||
// Using DataSource
|
||||
await AppDataSource
|
||||
.createQueryBuilder()
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.from(User2, "User2")
|
||||
.where(BadInput, { id: 1 }) // test: SQLInjectionPoint
|
||||
.getMany()
|
||||
|
||||
// Using entity manager
|
||||
await AppDataSource.manager
|
||||
.createQueryBuilder(User2, "User2").where("User2.id =:kind" + BadInput, { kind: '1' }).getMany() // test: SQLInjectionPoint
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2")
|
||||
.leftJoinAndSelect("user.photos", "photo", BadInput).getMany() // test: SQLInjectionPoint
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2").groupBy("User2.id").having(BadInput).getMany() // test: SQLInjectionPoint
|
||||
// orderBy
|
||||
// it is a little bit restrictive, e.g. sqlite don't support it at all
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2").where(BadInput, { // test: SQLInjectionPoint
|
||||
firstName: "Timber",
|
||||
})
|
||||
.where(
|
||||
new Brackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput); // test: SQLInjectionPoint
|
||||
})
|
||||
)
|
||||
.orderBy(BadInput).orWhere(BadInput).getMany() // test: SQLInjectionPoint
|
||||
|
||||
// relation
|
||||
AppDataSource.createQueryBuilder().relation(User, "name")
|
||||
.of(User)
|
||||
.select().where(BadInput).getMany().then(results => { // test: SQLInjectionPoint
|
||||
console.log(results)
|
||||
})
|
||||
|
||||
// Brackets
|
||||
await AppDataSource.createQueryBuilder(User2, "User2")
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput); // test: SQLInjectionPoint
|
||||
})
|
||||
).andWhere(
|
||||
new NotBrackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput) // test: SQLInjectionPoint
|
||||
}),
|
||||
).getMany()
|
||||
}).catch(error => console.log(error))
|
||||
30
javascript/ql/test/experimental/TypeOrm/tests.expected
Normal file
30
javascript/ql/test/experimental/TypeOrm/tests.expected
Normal file
@@ -0,0 +1,30 @@
|
||||
| PASSED | SQLInjectionPoint | test.ts:19:54:19:79 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:20:55:20:80 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:82:70:82:95 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:88:70:88:95 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:97:41:97:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:111:41:111:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:115:37:115:62 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:116:27:116:52 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:122:74:122:99 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:123:29:123:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:129:28:129:53 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:134:41:134:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:138:29:138:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:139:38:139:63 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:143:61:143:86 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:149:80:149:105 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:159:37:159:62 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:161:36:161:61 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:175:29:175:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:177:39:177:64 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:182:108:182:133 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:185:74:185:99 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:187:94:187:119 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:191:65:191:90 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:196:57:196:82 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:199:58:199:83 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:204:65:204:90 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:210:28:210:53 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:213:56:213:81 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:217:56:217:81 | // test ... onPoint |
|
||||
27
javascript/ql/test/experimental/TypeOrm/tests.ql
Normal file
27
javascript/ql/test/experimental/TypeOrm/tests.ql
Normal file
@@ -0,0 +1,27 @@
|
||||
import javascript
|
||||
|
||||
class InlineTest extends LineComment {
|
||||
string tests;
|
||||
|
||||
InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) }
|
||||
|
||||
string getPositiveTest() {
|
||||
result = tests.trim().splitAt(",").trim() and not result.matches("!%")
|
||||
}
|
||||
|
||||
predicate hasPositiveTest(string test) { test = this.getPositiveTest() }
|
||||
|
||||
predicate inNode(DataFlow::Node n) {
|
||||
this.getLocation().getFile() = n.getFile() and
|
||||
this.getLocation().getStartLine() = n.getStartLine()
|
||||
}
|
||||
}
|
||||
|
||||
import experimental.semmle.javascript.SQL
|
||||
|
||||
query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "SQLInjectionPoint" and
|
||||
exists(SQL::SqlString n | t.inNode(n))
|
||||
}
|
||||
15
javascript/ql/test/experimental/TypeOrm/tsconfig.json
Normal file
15
javascript/ql/test/experimental/TypeOrm/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"es5",
|
||||
"es6"
|
||||
],
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./build",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user