Skip to content

Commit 51ed824

Browse files
committed
Swift: Add more SQLite.swift models.
1 parent 6be01ea commit 51ed824

File tree

5 files changed

+73
-4
lines changed

5 files changed

+73
-4
lines changed

swift/ql/lib/codeql/swift/frameworks/Frameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
private import Alamofire.Alamofire
66
private import JavaScriptCore.JavaScriptCore
7+
private import SQL.SQL
78
private import StandardLibrary.StandardLibrary
89
private import UIKit.UIKit
910
private import Xml.Xml
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Provides models for SQL libraries.
3+
*/
4+
5+
import swift
6+
private import codeql.swift.dataflow.ExternalFlow
7+
8+
/**
9+
* A model for SQL library functions that permit taint flow.
10+
*/
11+
private class FilePathSummaries extends SummaryModelCsv {
12+
override predicate row(string row) {
13+
row =
14+
[
15+
// SQLite.Swift
16+
";;false;<-(_:_:);;;Argument[0..1];ReturnValue;taint",
17+
";Expression;true;init(_:_:);;;Argument[0];ReturnValue;taint",
18+
";Expression;true;init(_:_:);;;Argument[1].CollectionElement;ReturnValue;taint",
19+
";ExpressionType;true;init(_:);;;Argument[0];ReturnValue;taint",
20+
";ExpressionType;true;replace(_:with:);;;Argument[1];ReturnValue;taint",
21+
]
22+
}
23+
}

swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ private class CleartextStorageDatabaseSinks extends SinkModelCsv {
139139
";Statement;true;bind(_:);;;Argument[0];database-store",
140140
";Statement;true;run(_:);;;Argument[0];database-store",
141141
";Statement;true;scalar(_:);;;Argument[0];database-store",
142+
";QueryType;true;insert(_:);;;Argument[0];database-store",
143+
";QueryType;true;insert(_:_:);;;Argument[0..1];database-store",
144+
";QueryType;true;insert(or:_:);;;Argument[1];database-store",
145+
";QueryType;true;insertMany(_:);;;Argument[0];database-store",
146+
";QueryType;true;insertMany(or:_:);;;Argument[1];database-store",
147+
";QueryType;true;upsert(_:onConflictOf:);;;Argument[0];database-store",
148+
";QueryType;true;upsert(_:onConflictOf:setValues:);;;Argument[0];database-store",
149+
";QueryType;true;upsert(_:onConflictOf:setValues:);;;Argument[2];database-store",
150+
";QueryType;true;update(_:);;;Argument[0];database-store",
151+
";QueryType;true;update(_:_:);;;Argument[0..1];database-store",
152+
";QueryType;true;update(or:_:);;;Argument[1];database-store",
142153
]
143154
}
144155
}

swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ edges
4545
| SQLite.swift:169:23:169:61 | [...] [Collection element, Tuple element at index 1] | SQLite.swift:169:23:169:61 | [...] |
4646
| SQLite.swift:169:34:169:44 | (...) [Tuple element at index 1] | SQLite.swift:169:23:169:61 | [...] [Collection element, Tuple element at index 1] |
4747
| SQLite.swift:169:44:169:44 | mobilePhoneNumber | SQLite.swift:169:34:169:44 | (...) [Tuple element at index 1] |
48+
| SQLite.swift:179:40:179:54 | ... <-(_:_:) ... | SQLite.swift:179:40:179:54 | [...] |
49+
| SQLite.swift:179:40:179:54 | [...] | SQLite.swift:179:40:179:54 | [...] |
50+
| SQLite.swift:179:54:179:54 | mobilePhoneNumber | SQLite.swift:179:40:179:54 | ... <-(_:_:) ... |
51+
| SQLite.swift:182:26:182:40 | ... <-(_:_:) ... | SQLite.swift:182:26:182:40 | [...] |
52+
| SQLite.swift:182:26:182:40 | [...] | SQLite.swift:182:26:182:40 | [...] |
53+
| SQLite.swift:182:40:182:40 | mobilePhoneNumber | SQLite.swift:182:26:182:40 | ... <-(_:_:) ... |
54+
| SQLite.swift:184:27:184:41 | ... <-(_:_:) ... | SQLite.swift:184:27:184:41 | [...] |
55+
| SQLite.swift:184:27:184:41 | [...] | SQLite.swift:184:27:184:41 | [...] |
56+
| SQLite.swift:184:41:184:41 | mobilePhoneNumber | SQLite.swift:184:27:184:41 | ... <-(_:_:) ... |
57+
| SQLite.swift:186:26:186:89 | ... <-(_:_:) ... | SQLite.swift:186:26:186:89 | [...] |
58+
| SQLite.swift:186:26:186:89 | [...] | SQLite.swift:186:26:186:89 | [...] |
59+
| SQLite.swift:186:40:186:89 | call to replace(_:with:) | SQLite.swift:186:26:186:89 | ... <-(_:_:) ... |
60+
| SQLite.swift:186:72:186:72 | mobilePhoneNumber | SQLite.swift:186:40:186:89 | call to replace(_:with:) |
4861
| file://:0:0:0:0 | self | file://:0:0:0:0 | .value |
4962
| file://:0:0:0:0 | self | file://:0:0:0:0 | .value2 |
5063
| file://:0:0:0:0 | self [value] | file://:0:0:0:0 | .value |
@@ -297,6 +310,23 @@ nodes
297310
| SQLite.swift:169:23:169:61 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
298311
| SQLite.swift:169:34:169:44 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
299312
| SQLite.swift:169:44:169:44 | mobilePhoneNumber | semmle.label | mobilePhoneNumber |
313+
| SQLite.swift:179:40:179:54 | ... <-(_:_:) ... | semmle.label | ... <-(_:_:) ... |
314+
| SQLite.swift:179:40:179:54 | [...] | semmle.label | [...] |
315+
| SQLite.swift:179:40:179:54 | [...] | semmle.label | [...] |
316+
| SQLite.swift:179:54:179:54 | mobilePhoneNumber | semmle.label | mobilePhoneNumber |
317+
| SQLite.swift:182:26:182:40 | ... <-(_:_:) ... | semmle.label | ... <-(_:_:) ... |
318+
| SQLite.swift:182:26:182:40 | [...] | semmle.label | [...] |
319+
| SQLite.swift:182:26:182:40 | [...] | semmle.label | [...] |
320+
| SQLite.swift:182:40:182:40 | mobilePhoneNumber | semmle.label | mobilePhoneNumber |
321+
| SQLite.swift:184:27:184:41 | ... <-(_:_:) ... | semmle.label | ... <-(_:_:) ... |
322+
| SQLite.swift:184:27:184:41 | [...] | semmle.label | [...] |
323+
| SQLite.swift:184:27:184:41 | [...] | semmle.label | [...] |
324+
| SQLite.swift:184:41:184:41 | mobilePhoneNumber | semmle.label | mobilePhoneNumber |
325+
| SQLite.swift:186:26:186:89 | ... <-(_:_:) ... | semmle.label | ... <-(_:_:) ... |
326+
| SQLite.swift:186:26:186:89 | [...] | semmle.label | [...] |
327+
| SQLite.swift:186:26:186:89 | [...] | semmle.label | [...] |
328+
| SQLite.swift:186:40:186:89 | call to replace(_:with:) | semmle.label | call to replace(_:with:) |
329+
| SQLite.swift:186:72:186:72 | mobilePhoneNumber | semmle.label | mobilePhoneNumber |
300330
| file://:0:0:0:0 | .value | semmle.label | .value |
301331
| file://:0:0:0:0 | .value | semmle.label | .value |
302332
| file://:0:0:0:0 | .value2 | semmle.label | .value2 |
@@ -612,6 +642,10 @@ subpaths
612642
| SQLite.swift:167:21:167:59 | [...] | SQLite.swift:167:42:167:42 | mobilePhoneNumber | SQLite.swift:167:21:167:59 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:167:42:167:42 | mobilePhoneNumber | mobilePhoneNumber |
613643
| SQLite.swift:168:20:168:58 | [...] | SQLite.swift:168:41:168:41 | mobilePhoneNumber | SQLite.swift:168:20:168:58 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:168:41:168:41 | mobilePhoneNumber | mobilePhoneNumber |
614644
| SQLite.swift:169:23:169:61 | [...] | SQLite.swift:169:44:169:44 | mobilePhoneNumber | SQLite.swift:169:23:169:61 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:169:44:169:44 | mobilePhoneNumber | mobilePhoneNumber |
645+
| SQLite.swift:179:40:179:54 | [...] | SQLite.swift:179:54:179:54 | mobilePhoneNumber | SQLite.swift:179:40:179:54 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:179:54:179:54 | mobilePhoneNumber | mobilePhoneNumber |
646+
| SQLite.swift:182:26:182:40 | [...] | SQLite.swift:182:40:182:40 | mobilePhoneNumber | SQLite.swift:182:26:182:40 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:182:40:182:40 | mobilePhoneNumber | mobilePhoneNumber |
647+
| SQLite.swift:184:27:184:41 | [...] | SQLite.swift:184:41:184:41 | mobilePhoneNumber | SQLite.swift:184:27:184:41 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:184:41:184:41 | mobilePhoneNumber | mobilePhoneNumber |
648+
| SQLite.swift:186:26:186:89 | [...] | SQLite.swift:186:72:186:72 | mobilePhoneNumber | SQLite.swift:186:26:186:89 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | SQLite.swift:186:72:186:72 | mobilePhoneNumber | mobilePhoneNumber |
615649
| sqlite3_c_api.swift:46:27:46:27 | insertQuery | sqlite3_c_api.swift:42:69:42:69 | medicalNotes | sqlite3_c_api.swift:46:27:46:27 | insertQuery | This operation stores 'insertQuery' in a database. It may contain unencrypted sensitive data from $@. | sqlite3_c_api.swift:42:69:42:69 | medicalNotes | medicalNotes |
616650
| sqlite3_c_api.swift:47:27:47:27 | updateQuery | sqlite3_c_api.swift:43:49:43:49 | medicalNotes | sqlite3_c_api.swift:47:27:47:27 | updateQuery | This operation stores 'updateQuery' in a database. It may contain unencrypted sensitive data from $@. | sqlite3_c_api.swift:43:49:43:49 | medicalNotes | medicalNotes |
617651
| sqlite3_c_api.swift:58:36:58:36 | medicalNotes | sqlite3_c_api.swift:58:36:58:36 | medicalNotes | sqlite3_c_api.swift:58:36:58:36 | medicalNotes | This operation stores 'medicalNotes' in a database. It may contain unencrypted sensitive data from $@. | sqlite3_c_api.swift:58:36:58:36 | medicalNotes | medicalNotes |

swift/ql/test/query-tests/Security/CWE-311/SQLite.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,13 @@ func test_sqlite_swift_api(db: Connection, id: Int, mobilePhoneNumber: String) t
176176
let filter = table.filter(idExpr == id) // GOOD
177177

178178
try db.run(table.insert(idExpr <- id, numberExpr <- "123")) // GOOD
179-
try db.run(table.insert(idExpr <- id, numberExpr <- mobilePhoneNumber)) // BAD (sensitive data) [NOT DETECTED]
179+
try db.run(table.insert(idExpr <- id, numberExpr <- mobilePhoneNumber)) // BAD (sensitive data)
180180

181181
try db.run(table.update(numberExpr <- "123")) // GOOD
182-
try db.run(table.update(numberExpr <- mobilePhoneNumber)) // BAD (sensitive data) [NOT DETECTED]
182+
try db.run(table.update(numberExpr <- mobilePhoneNumber)) // BAD (sensitive data)
183183
try db.run(filter.update(numberExpr <- "123")) // GOOD
184-
try db.run(filter.update(numberExpr <- mobilePhoneNumber)) // BAD (sensitive data) [NOT DETECTED]
184+
try db.run(filter.update(numberExpr <- mobilePhoneNumber)) // BAD (sensitive data)
185185
try db.run(table.update(numberExpr <- numberExpr.replace("123", with: "456"))) // GOOD
186-
try db.run(table.update(numberExpr <- numberExpr.replace("123", with: mobilePhoneNumber))) // BAD (sensitive data) [NOT DETECTED]
186+
try db.run(table.update(numberExpr <- numberExpr.replace("123", with: mobilePhoneNumber))) // BAD (sensitive data)
187187
// (much more complex query construction is possible in SQLite.swift)
188188
}

0 commit comments

Comments
 (0)