Skip to content

Commit 976b040

Browse files
authored
Merge pull request github#11876 from geoffw0/coredata
Swift: Improve Core Data sinks for swift/cleartext-storage-database
2 parents 05c80b3 + 5d6f243 commit 976b040

File tree

5 files changed

+183
-8
lines changed

5 files changed

+183
-8
lines changed

swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.ql

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,25 @@ abstract class Stored extends DataFlow::Node { }
2727
*/
2828
class CoreDataStore extends Stored {
2929
CoreDataStore() {
30-
// values written into Core Data objects are a sink
30+
// values written into Core Data objects through `set*Value` methods are a sink.
3131
exists(CallExpr call |
3232
call.getStaticTarget()
3333
.(MethodDecl)
3434
.hasQualifiedName("NSManagedObject",
3535
["setValue(_:forKey:)", "setPrimitiveValue(_:forKey:)"]) and
3636
call.getArgument(0).getExpr() = this.asExpr()
3737
)
38+
or
39+
// any write into a class derived from `NSManagedObject` is a sink. For
40+
// example in `coreDataObj.data = sensitive` the post-update node corresponding
41+
// with `coreDataObj.data` is a sink.
42+
// (ideally this would be only members with the `@NSManaged` attribute)
43+
exists(ClassOrStructDecl cd, Expr e |
44+
cd.getABaseTypeDecl*().getName() = "NSManagedObject" and
45+
this.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = e and
46+
e.getFullyConverted().getType() = cd.getType() and
47+
not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl
48+
)
3849
}
3950
}
4051

@@ -141,12 +152,13 @@ class CleartextStorageConfig extends TaintTracking::Configuration {
141152
}
142153

143154
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
144-
// flow out from fields of a `RealmSwiftObject` at the sink, for example in
145-
// `realmObj.data = sensitive`.
155+
// flow out from fields of an `NSManagedObject` or `RealmSwiftObject` at the sink,
156+
// for example in `realmObj.data = sensitive`.
146157
isSink(node) and
147-
exists(ClassOrStructDecl cd |
148-
c.getAReadContent().(DataFlow::Content::FieldContent).getField() = cd.getAMember() and
149-
cd.getABaseTypeDecl*().getName() = "RealmSwiftObject"
158+
exists(ClassOrStructDecl cd, IterableDeclContext cx |
159+
cd.getABaseTypeDecl*().getName() = ["NSManagedObject", "RealmSwiftObject"] and
160+
cx.getNominalTypeDecl() = cd and
161+
c.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember()
150162
)
151163
or
152164
// any default implicit reads

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
11
edges
22
| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [data] : |
3+
| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : |
4+
| testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | value : |
5+
| testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : | testCoreData2.swift:37:2:37:2 | [post] obj |
6+
| testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : |
7+
| testCoreData2.swift:39:2:39:2 | [post] obj [myBankAccountNumber] : | testCoreData2.swift:39:2:39:2 | [post] obj |
8+
| testCoreData2.swift:39:28:39:28 | bankAccountNo : | testCoreData2.swift:39:2:39:2 | [post] obj [myBankAccountNumber] : |
9+
| testCoreData2.swift:41:2:41:2 | [post] obj [myBankAccountNumber2] : | testCoreData2.swift:41:2:41:2 | [post] obj |
10+
| testCoreData2.swift:41:29:41:29 | bankAccountNo : | testCoreData2.swift:41:2:41:2 | [post] obj [myBankAccountNumber2] : |
11+
| testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : | testCoreData2.swift:43:2:43:2 | [post] obj |
12+
| testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : |
13+
| testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : |
14+
| testCoreData2.swift:46:2:46:10 | [post] ...? [myValue] : | testCoreData2.swift:46:2:46:10 | [post] ...? |
15+
| testCoreData2.swift:46:22:46:22 | bankAccountNo : | testCoreData2.swift:46:2:46:10 | [post] ...? [myValue] : |
16+
| testCoreData2.swift:48:2:48:10 | [post] ...? [myBankAccountNumber] : | testCoreData2.swift:48:2:48:10 | [post] ...? |
17+
| testCoreData2.swift:48:34:48:34 | bankAccountNo : | testCoreData2.swift:48:2:48:10 | [post] ...? [myBankAccountNumber] : |
18+
| testCoreData2.swift:50:2:50:10 | [post] ...? [myBankAccountNumber2] : | testCoreData2.swift:50:2:50:10 | [post] ...? |
19+
| testCoreData2.swift:50:35:50:35 | bankAccountNo : | testCoreData2.swift:50:2:50:10 | [post] ...? [myBankAccountNumber2] : |
20+
| testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : | testCoreData2.swift:52:2:52:10 | [post] ...? |
21+
| testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : |
22+
| testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : |
23+
| testCoreData2.swift:57:3:57:3 | [post] obj [myBankAccountNumber] : | testCoreData2.swift:57:3:57:3 | [post] obj |
24+
| testCoreData2.swift:57:29:57:29 | bankAccountNo : | testCoreData2.swift:57:3:57:3 | [post] obj [myBankAccountNumber] : |
325
| testCoreData.swift:18:19:18:26 | value : | testCoreData.swift:19:12:19:12 | value |
426
| testCoreData.swift:31:3:31:3 | newValue : | testCoreData.swift:32:13:32:13 | newValue |
527
| testCoreData.swift:61:25:61:25 | password : | testCoreData.swift:18:19:18:26 | value : |
28+
| testCoreData.swift:64:2:64:2 | [post] obj [myValue] : | testCoreData.swift:64:2:64:2 | [post] obj |
629
| testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:31:3:31:3 | newValue : |
30+
| testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:64:2:64:2 | [post] obj [myValue] : |
731
| testCoreData.swift:77:24:77:24 | x : | testCoreData.swift:78:15:78:15 | x |
832
| testCoreData.swift:80:10:80:22 | call to getPassword() : | testCoreData.swift:81:15:81:15 | y |
933
| testCoreData.swift:91:10:91:10 | passwd : | testCoreData.swift:95:15:95:15 | x |
@@ -75,7 +99,37 @@ edges
7599
| testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:59:2:59:2 | [post] g [data] : |
76100
nodes
77101
| file://:0:0:0:0 | [post] self [data] : | semmle.label | [post] self [data] : |
102+
| file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | semmle.label | [post] self [notStoredBankAccountNumber] : |
78103
| file://:0:0:0:0 | value : | semmle.label | value : |
104+
| file://:0:0:0:0 | value : | semmle.label | value : |
105+
| testCoreData2.swift:23:13:23:13 | value : | semmle.label | value : |
106+
| testCoreData2.swift:37:2:37:2 | [post] obj | semmle.label | [post] obj |
107+
| testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : | semmle.label | [post] obj [myValue] : |
108+
| testCoreData2.swift:37:16:37:16 | bankAccountNo : | semmle.label | bankAccountNo : |
109+
| testCoreData2.swift:39:2:39:2 | [post] obj | semmle.label | [post] obj |
110+
| testCoreData2.swift:39:2:39:2 | [post] obj [myBankAccountNumber] : | semmle.label | [post] obj [myBankAccountNumber] : |
111+
| testCoreData2.swift:39:28:39:28 | bankAccountNo : | semmle.label | bankAccountNo : |
112+
| testCoreData2.swift:41:2:41:2 | [post] obj | semmle.label | [post] obj |
113+
| testCoreData2.swift:41:2:41:2 | [post] obj [myBankAccountNumber2] : | semmle.label | [post] obj [myBankAccountNumber2] : |
114+
| testCoreData2.swift:41:29:41:29 | bankAccountNo : | semmle.label | bankAccountNo : |
115+
| testCoreData2.swift:43:2:43:2 | [post] obj | semmle.label | [post] obj |
116+
| testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : | semmle.label | [post] obj [notStoredBankAccountNumber] : |
117+
| testCoreData2.swift:43:35:43:35 | bankAccountNo : | semmle.label | bankAccountNo : |
118+
| testCoreData2.swift:46:2:46:10 | [post] ...? | semmle.label | [post] ...? |
119+
| testCoreData2.swift:46:2:46:10 | [post] ...? [myValue] : | semmle.label | [post] ...? [myValue] : |
120+
| testCoreData2.swift:46:22:46:22 | bankAccountNo : | semmle.label | bankAccountNo : |
121+
| testCoreData2.swift:48:2:48:10 | [post] ...? | semmle.label | [post] ...? |
122+
| testCoreData2.swift:48:2:48:10 | [post] ...? [myBankAccountNumber] : | semmle.label | [post] ...? [myBankAccountNumber] : |
123+
| testCoreData2.swift:48:34:48:34 | bankAccountNo : | semmle.label | bankAccountNo : |
124+
| testCoreData2.swift:50:2:50:10 | [post] ...? | semmle.label | [post] ...? |
125+
| testCoreData2.swift:50:2:50:10 | [post] ...? [myBankAccountNumber2] : | semmle.label | [post] ...? [myBankAccountNumber2] : |
126+
| testCoreData2.swift:50:35:50:35 | bankAccountNo : | semmle.label | bankAccountNo : |
127+
| testCoreData2.swift:52:2:52:10 | [post] ...? | semmle.label | [post] ...? |
128+
| testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : | semmle.label | [post] ...? [notStoredBankAccountNumber] : |
129+
| testCoreData2.swift:52:41:52:41 | bankAccountNo : | semmle.label | bankAccountNo : |
130+
| testCoreData2.swift:57:3:57:3 | [post] obj | semmle.label | [post] obj |
131+
| testCoreData2.swift:57:3:57:3 | [post] obj [myBankAccountNumber] : | semmle.label | [post] obj [myBankAccountNumber] : |
132+
| testCoreData2.swift:57:29:57:29 | bankAccountNo : | semmle.label | bankAccountNo : |
79133
| testCoreData.swift:18:19:18:26 | value : | semmle.label | value : |
80134
| testCoreData.swift:19:12:19:12 | value | semmle.label | value |
81135
| testCoreData.swift:31:3:31:3 | newValue : | semmle.label | newValue : |
@@ -84,6 +138,8 @@ nodes
84138
| testCoreData.swift:51:24:51:24 | password | semmle.label | password |
85139
| testCoreData.swift:58:15:58:15 | password | semmle.label | password |
86140
| testCoreData.swift:61:25:61:25 | password : | semmle.label | password : |
141+
| testCoreData.swift:64:2:64:2 | [post] obj | semmle.label | [post] obj |
142+
| testCoreData.swift:64:2:64:2 | [post] obj [myValue] : | semmle.label | [post] obj [myValue] : |
87143
| testCoreData.swift:64:16:64:16 | password : | semmle.label | password : |
88144
| testCoreData.swift:77:24:77:24 | x : | semmle.label | x : |
89145
| testCoreData.swift:78:15:78:15 | x | semmle.label | x |
@@ -212,16 +268,28 @@ nodes
212268
| testRealm.swift:59:2:59:2 | [post] g [data] : | semmle.label | [post] g [data] : |
213269
| testRealm.swift:59:11:59:11 | myPassword : | semmle.label | myPassword : |
214270
subpaths
271+
| testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : |
272+
| testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : |
215273
| testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:34:2:34:2 | [post] a [data] : |
216274
| testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:42:2:42:2 | [post] c [data] : |
217275
| testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:52:2:52:3 | [post] ...! [data] : |
218276
| testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:59:2:59:2 | [post] g [data] : |
219277
#select
278+
| testCoreData2.swift:37:2:37:2 | obj | testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:37:16:37:16 | bankAccountNo : | bankAccountNo |
279+
| testCoreData2.swift:39:2:39:2 | obj | testCoreData2.swift:39:28:39:28 | bankAccountNo : | testCoreData2.swift:39:2:39:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:39:28:39:28 | bankAccountNo : | bankAccountNo |
280+
| testCoreData2.swift:41:2:41:2 | obj | testCoreData2.swift:41:29:41:29 | bankAccountNo : | testCoreData2.swift:41:2:41:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:41:29:41:29 | bankAccountNo : | bankAccountNo |
281+
| testCoreData2.swift:43:2:43:2 | obj | testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:43:2:43:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:43:35:43:35 | bankAccountNo : | bankAccountNo |
282+
| testCoreData2.swift:46:2:46:10 | ...? | testCoreData2.swift:46:22:46:22 | bankAccountNo : | testCoreData2.swift:46:2:46:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:46:22:46:22 | bankAccountNo : | bankAccountNo |
283+
| testCoreData2.swift:48:2:48:10 | ...? | testCoreData2.swift:48:34:48:34 | bankAccountNo : | testCoreData2.swift:48:2:48:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:48:34:48:34 | bankAccountNo : | bankAccountNo |
284+
| testCoreData2.swift:50:2:50:10 | ...? | testCoreData2.swift:50:35:50:35 | bankAccountNo : | testCoreData2.swift:50:2:50:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:50:35:50:35 | bankAccountNo : | bankAccountNo |
285+
| testCoreData2.swift:52:2:52:10 | ...? | testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:52:2:52:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:52:41:52:41 | bankAccountNo : | bankAccountNo |
286+
| testCoreData2.swift:57:3:57:3 | obj | testCoreData2.swift:57:29:57:29 | bankAccountNo : | testCoreData2.swift:57:3:57:3 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:57:29:57:29 | bankAccountNo : | bankAccountNo |
220287
| testCoreData.swift:19:12:19:12 | value | testCoreData.swift:61:25:61:25 | password : | testCoreData.swift:19:12:19:12 | value | This operation stores 'value' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:61:25:61:25 | password : | password |
221288
| testCoreData.swift:32:13:32:13 | newValue | testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:32:13:32:13 | newValue | This operation stores 'newValue' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:64:16:64:16 | password : | password |
222289
| testCoreData.swift:48:15:48:15 | password | testCoreData.swift:48:15:48:15 | password | testCoreData.swift:48:15:48:15 | password | This operation stores 'password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:48:15:48:15 | password | password |
223290
| testCoreData.swift:51:24:51:24 | password | testCoreData.swift:51:24:51:24 | password | testCoreData.swift:51:24:51:24 | password | This operation stores 'password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:51:24:51:24 | password | password |
224291
| testCoreData.swift:58:15:58:15 | password | testCoreData.swift:58:15:58:15 | password | testCoreData.swift:58:15:58:15 | password | This operation stores 'password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:58:15:58:15 | password | password |
292+
| testCoreData.swift:64:2:64:2 | obj | testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:64:2:64:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:64:16:64:16 | password : | password |
225293
| testCoreData.swift:78:15:78:15 | x | testCoreData.swift:77:24:77:24 | x : | testCoreData.swift:78:15:78:15 | x | This operation stores 'x' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:77:24:77:24 | x : | x |
226294
| testCoreData.swift:81:15:81:15 | y | testCoreData.swift:80:10:80:22 | call to getPassword() : | testCoreData.swift:81:15:81:15 | y | This operation stores 'y' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:80:10:80:22 | call to getPassword() : | call to getPassword() |
227295
| testCoreData.swift:85:15:85:17 | .password | testCoreData.swift:85:15:85:17 | .password | testCoreData.swift:85:15:85:17 | .password | This operation stores '.password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:85:15:85:17 | .password | .password |

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,34 @@
88
| testAlamofire.swift:195:64:195:64 | password | label:password, type:credential |
99
| testAlamofire.swift:205:62:205:62 | password | label:password, type:credential |
1010
| testAlamofire.swift:213:65:213:65 | password | label:password, type:credential |
11+
| testCoreData2.swift:37:16:37:16 | bankAccountNo | label:bankAccountNo, type:private information |
12+
| testCoreData2.swift:38:2:38:6 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
13+
| testCoreData2.swift:39:2:39:6 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
14+
| testCoreData2.swift:39:28:39:28 | bankAccountNo | label:bankAccountNo, type:private information |
15+
| testCoreData2.swift:40:2:40:6 | .myBankAccountNumber2 | label:myBankAccountNumber2, type:private information |
16+
| testCoreData2.swift:41:2:41:6 | .myBankAccountNumber2 | label:myBankAccountNumber2, type:private information |
17+
| testCoreData2.swift:41:29:41:29 | bankAccountNo | label:bankAccountNo, type:private information |
18+
| testCoreData2.swift:42:2:42:6 | .notStoredBankAccountNumber | label:notStoredBankAccountNumber, type:private information |
19+
| testCoreData2.swift:43:2:43:6 | .notStoredBankAccountNumber | label:notStoredBankAccountNumber, type:private information |
20+
| testCoreData2.swift:43:35:43:35 | bankAccountNo | label:bankAccountNo, type:private information |
21+
| testCoreData2.swift:46:22:46:22 | bankAccountNo | label:bankAccountNo, type:private information |
22+
| testCoreData2.swift:47:2:47:12 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
23+
| testCoreData2.swift:48:2:48:12 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
24+
| testCoreData2.swift:48:34:48:34 | bankAccountNo | label:bankAccountNo, type:private information |
25+
| testCoreData2.swift:49:2:49:12 | .myBankAccountNumber2 | label:myBankAccountNumber2, type:private information |
26+
| testCoreData2.swift:50:2:50:12 | .myBankAccountNumber2 | label:myBankAccountNumber2, type:private information |
27+
| testCoreData2.swift:50:35:50:35 | bankAccountNo | label:bankAccountNo, type:private information |
28+
| testCoreData2.swift:51:2:51:12 | .notStoredBankAccountNumber | label:notStoredBankAccountNumber, type:private information |
29+
| testCoreData2.swift:52:2:52:12 | .notStoredBankAccountNumber | label:notStoredBankAccountNumber, type:private information |
30+
| testCoreData2.swift:52:41:52:41 | bankAccountNo | label:bankAccountNo, type:private information |
31+
| testCoreData2.swift:57:3:57:7 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
32+
| testCoreData2.swift:57:29:57:29 | bankAccountNo | label:bankAccountNo, type:private information |
33+
| testCoreData2.swift:60:4:60:8 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
34+
| testCoreData2.swift:60:30:60:30 | bankAccountNo | label:bankAccountNo, type:private information |
35+
| testCoreData2.swift:62:4:62:8 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
36+
| testCoreData2.swift:62:30:62:30 | bankAccountNo | label:bankAccountNo, type:private information |
37+
| testCoreData2.swift:65:3:65:7 | .myBankAccountNumber | label:myBankAccountNumber, type:private information |
38+
| testCoreData2.swift:65:29:65:29 | bankAccountNo | label:bankAccountNo, type:private information |
1139
| testCoreData.swift:48:15:48:15 | password | label:password, type:credential |
1240
| testCoreData.swift:51:24:51:24 | password | label:password, type:credential |
1341
| testCoreData.swift:58:15:58:15 | password | label:password, type:credential |

0 commit comments

Comments
 (0)