;
-from CommandInjectionFlow::PathNode sourceNode, CommandInjectionFlow::PathNode sinkNode
-where CommandInjectionFlow::flowPath(sourceNode, sinkNode)
-select sinkNode.getNode(), sourceNode, sinkNode, "This command depends on a $@.",
- sourceNode.getNode(), "user-provided value"
+import CommandInjectionFlow::PathGraph
+
+from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink
+where CommandInjectionFlow::flowPath(source, sink)
+select sink.getNode(), source, sink, "This command depends on a $@.", source.getNode(),
+ "user-provided value"
diff --git a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected
index 6e6b86231495..2a0d50ee5f7d 100644
--- a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected
+++ b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected
@@ -1,300 +1,19 @@
+#select
+| CommandInjection.swift:150:42:150:61 | userControlledString | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:150:42:150:61 | userControlledString | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
+| CommandInjection.swift:160:41:160:74 | ... ! | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:160:41:160:74 | ... ! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
edges
-| CommandInjection.swift:64:22:64:33 | command | CommandInjection.swift:68:16:68:16 | command | provenance | |
-| CommandInjection.swift:64:22:64:33 | command [some:0] | CommandInjection.swift:68:16:68:16 | command [some:0] | provenance | |
-| CommandInjection.swift:68:16:68:16 | command | CommandInjection.swift:68:16:68:16 | command [some:0] | provenance | |
-| CommandInjection.swift:75:8:75:12 | let ...? [some:0, some:0] | CommandInjection.swift:75:12:75:12 | userControlledString [some:0] | provenance | |
-| CommandInjection.swift:75:8:75:12 | let ...? [some:0] | CommandInjection.swift:75:12:75:12 | userControlledString | provenance | |
-| CommandInjection.swift:75:12:75:12 | userControlledString | CommandInjection.swift:81:27:81:27 | userControlledString | provenance | |
-| CommandInjection.swift:75:12:75:12 | userControlledString | CommandInjection.swift:84:43:84:43 | userControlledString | provenance | |
-| CommandInjection.swift:75:12:75:12 | userControlledString [some:0] | CommandInjection.swift:84:43:84:43 | userControlledString [some:0] | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0] | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | CommandInjection.swift:81:27:81:27 | userControlledString | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | CommandInjection.swift:84:43:84:43 | userControlledString | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0, some:0] | CommandInjection.swift:75:8:75:12 | let ...? [some:0, some:0] | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:75:8:75:12 | let ...? [some:0] | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0, some:0] | provenance | |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:84:43:84:43 | userControlledString [some:0] | provenance | |
-| CommandInjection.swift:81:20:81:47 | [...] [Collection element] | CommandInjection.swift:81:2:81:2 | [post] task1 | provenance | |
-| CommandInjection.swift:81:27:81:27 | userControlledString | CommandInjection.swift:81:20:81:47 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:84:5:84:9 | let ...? [some:0] | CommandInjection.swift:84:9:84:9 | validatedString | provenance | |
-| CommandInjection.swift:84:9:84:9 | validatedString | CommandInjection.swift:87:31:87:31 | validatedString | provenance | |
-| CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) | CommandInjection.swift:87:31:87:31 | validatedString | provenance | |
-| CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) [some:0] | CommandInjection.swift:84:5:84:9 | let ...? [some:0] | provenance | |
-| CommandInjection.swift:84:43:84:43 | userControlledString | CommandInjection.swift:64:22:64:33 | command | provenance | |
-| CommandInjection.swift:84:43:84:43 | userControlledString | CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) | provenance | |
-| CommandInjection.swift:84:43:84:43 | userControlledString | CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) [some:0] | provenance | |
-| CommandInjection.swift:84:43:84:43 | userControlledString [some:0] | CommandInjection.swift:64:22:64:33 | command [some:0] | provenance | |
-| CommandInjection.swift:84:43:84:43 | userControlledString [some:0] | CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) [some:0] | provenance | |
-| CommandInjection.swift:87:24:87:46 | [...] [Collection element] | CommandInjection.swift:87:6:87:6 | [post] task2 | provenance | |
-| CommandInjection.swift:87:31:87:31 | validatedString | CommandInjection.swift:87:24:87:46 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:99:20:99:40 | arguments [Collection element] | CommandInjection.swift:100:20:100:20 | arguments [Collection element] | provenance | |
-| CommandInjection.swift:100:20:100:20 | arguments [Collection element] | CommandInjection.swift:100:3:100:3 | [post] self | provenance | |
-| CommandInjection.swift:105:8:105:12 | let ...? [some:0] | CommandInjection.swift:105:12:105:12 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:120:36:120:36 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:121:28:121:28 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:125:45:125:45 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:126:36:126:36 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:127:28:127:36 | ... .+(_:_:) ... | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:131:46:131:46 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:132:22:132:22 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:136:45:136:45 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:137:36:137:36 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:138:21:138:21 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:139:22:139:22 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:150:42:150:42 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:151:75:151:75 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:154:35:154:35 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:155:70:155:70 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:160:53:160:53 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:163:52:163:52 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:164:33:164:33 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:12 | userControlledString | CommandInjection.swift:166:57:166:57 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) [some:0] | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:120:36:120:36 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:121:28:121:28 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:125:45:125:45 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:126:36:126:36 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:127:28:127:36 | ... .+(_:_:) ... | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:131:46:131:46 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:132:22:132:22 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:136:45:136:45 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:137:36:137:36 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:138:21:138:21 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:139:22:139:22 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:150:42:150:42 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:151:75:151:75 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:154:35:154:35 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:155:70:155:70 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:160:53:160:53 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:163:52:163:52 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:164:33:164:33 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:166:57:166:57 | userControlledString | provenance | |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:105:8:105:12 | let ...? [some:0] | provenance | |
-| CommandInjection.swift:120:24:120:56 | call to URL.init(string:) [some:0] | CommandInjection.swift:120:24:120:57 | ...! | provenance | |
-| CommandInjection.swift:120:24:120:57 | ...! | CommandInjection.swift:120:2:120:2 | [post] task3 | provenance | |
-| CommandInjection.swift:120:36:120:36 | userControlledString | CommandInjection.swift:120:24:120:56 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:121:20:121:48 | [...] [Collection element] | CommandInjection.swift:121:2:121:2 | [post] task3 | provenance | |
-| CommandInjection.swift:121:28:121:28 | userControlledString | CommandInjection.swift:121:20:121:48 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:125:24:125:65 | call to URL.init(fileURLWithPath:) | CommandInjection.swift:125:2:125:2 | [post] task4 | provenance | |
-| CommandInjection.swift:125:45:125:45 | userControlledString | CommandInjection.swift:125:24:125:65 | call to URL.init(fileURLWithPath:) | provenance | |
-| CommandInjection.swift:126:24:126:56 | call to URL.init(string:) [some:0] | CommandInjection.swift:126:24:126:57 | ...! | provenance | |
-| CommandInjection.swift:126:24:126:57 | ...! | CommandInjection.swift:126:2:126:2 | [post] task4 | provenance | |
-| CommandInjection.swift:126:36:126:36 | userControlledString | CommandInjection.swift:126:24:126:56 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:127:20:127:56 | [...] [Collection element] | CommandInjection.swift:127:2:127:2 | [post] task4 | provenance | |
-| CommandInjection.swift:127:28:127:36 | ... .+(_:_:) ... | CommandInjection.swift:127:20:127:56 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:131:25:131:66 | call to URL.init(fileURLWithPath:) | CommandInjection.swift:131:2:131:7 | [post] ...? | provenance | |
-| CommandInjection.swift:131:46:131:46 | userControlledString | CommandInjection.swift:131:25:131:66 | call to URL.init(fileURLWithPath:) | provenance | |
-| CommandInjection.swift:132:21:132:42 | [...] [Collection element] | CommandInjection.swift:132:2:132:7 | [post] ...? | provenance | |
-| CommandInjection.swift:132:22:132:22 | userControlledString | CommandInjection.swift:132:21:132:42 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:136:24:136:65 | call to URL.init(fileURLWithPath:) | CommandInjection.swift:136:2:136:2 | [post] task6 | provenance | |
-| CommandInjection.swift:136:45:136:45 | userControlledString | CommandInjection.swift:136:24:136:65 | call to URL.init(fileURLWithPath:) | provenance | |
-| CommandInjection.swift:137:24:137:56 | call to URL.init(string:) [some:0] | CommandInjection.swift:137:24:137:57 | ...! | provenance | |
-| CommandInjection.swift:137:24:137:57 | ...! | CommandInjection.swift:137:2:137:2 | [post] task6 | provenance | |
-| CommandInjection.swift:137:36:137:36 | userControlledString | CommandInjection.swift:137:24:137:56 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:138:20:138:41 | [...] [Collection element] | CommandInjection.swift:138:2:138:2 | [post] task6 | provenance | |
-| CommandInjection.swift:138:21:138:21 | userControlledString | CommandInjection.swift:138:20:138:41 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:139:21:139:42 | [...] [Collection element] | CommandInjection.swift:99:20:99:40 | arguments [Collection element] | provenance | |
-| CommandInjection.swift:139:22:139:22 | userControlledString | CommandInjection.swift:139:21:139:42 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:151:75:151:75 | userControlledString | CommandInjection.swift:151:67:151:95 | [...] | provenance | |
-| CommandInjection.swift:154:23:154:55 | call to URL.init(string:) [some:0] | CommandInjection.swift:154:23:154:56 | ...! | provenance | |
-| CommandInjection.swift:154:35:154:35 | userControlledString | CommandInjection.swift:154:23:154:55 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:155:70:155:70 | userControlledString | CommandInjection.swift:155:62:155:90 | [...] | provenance | |
-| CommandInjection.swift:160:41:160:73 | call to URL.init(string:) [some:0] | CommandInjection.swift:160:41:160:74 | ...! | provenance | |
-| CommandInjection.swift:160:53:160:53 | userControlledString | CommandInjection.swift:160:41:160:73 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:163:40:163:72 | call to URL.init(string:) [some:0] | CommandInjection.swift:163:40:163:73 | ...! | provenance | |
-| CommandInjection.swift:163:40:163:72 | call to URL.init(string:) [some:0] | CommandInjection.swift:163:40:163:73 | ...! | provenance | |
-| CommandInjection.swift:163:40:163:73 | ...! | file://:0:0:0:0 | url | provenance | |
-| CommandInjection.swift:163:52:163:52 | userControlledString | CommandInjection.swift:163:40:163:72 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:164:33:164:33 | userControlledString | CommandInjection.swift:164:32:164:53 | [...] | provenance | |
-| CommandInjection.swift:166:45:166:77 | call to URL.init(string:) [some:0] | CommandInjection.swift:166:45:166:78 | ...! | provenance | |
-| CommandInjection.swift:166:45:166:77 | call to URL.init(string:) [some:0] | CommandInjection.swift:166:45:166:78 | ...! | provenance | |
-| CommandInjection.swift:166:45:166:78 | ...! | file://:0:0:0:0 | url | provenance | |
-| CommandInjection.swift:166:57:166:57 | userControlledString | CommandInjection.swift:166:45:166:77 | call to URL.init(string:) [some:0] | provenance | |
-| CommandInjection.swift:193:3:193:3 | newValue [Collection element] | CommandInjection.swift:194:19:194:19 | newValue [Collection element] | provenance | |
-| CommandInjection.swift:193:3:193:3 | newValue [Collection element] | CommandInjection.swift:195:20:195:20 | newValue [Collection element] | provenance | |
-| CommandInjection.swift:193:3:193:3 | newValue [Collection element] | CommandInjection.swift:196:19:196:19 | newValue [Collection element] | provenance | |
-| CommandInjection.swift:194:19:194:19 | newValue [Collection element] | CommandInjection.swift:194:4:194:4 | [post] getter for .p1 | provenance | |
-| CommandInjection.swift:195:20:195:20 | newValue [Collection element] | CommandInjection.swift:195:4:195:6 | [post] ...! | provenance | |
-| CommandInjection.swift:196:19:196:19 | newValue [Collection element] | CommandInjection.swift:196:4:196:4 | [post] ...! | provenance | |
-| CommandInjection.swift:201:9:201:13 | let ...? [some:0] | CommandInjection.swift:201:13:201:13 | userControlledString | provenance | |
-| CommandInjection.swift:201:13:201:13 | userControlledString | CommandInjection.swift:205:19:205:19 | userControlledString | provenance | |
-| CommandInjection.swift:201:13:201:13 | userControlledString | CommandInjection.swift:211:31:211:31 | userControlledString | provenance | |
-| CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) [some:0] | provenance | |
-| CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:205:19:205:19 | userControlledString | provenance | |
-| CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:211:31:211:31 | userControlledString | provenance | |
-| CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:201:9:201:13 | let ...? [some:0] | provenance | |
-| CommandInjection.swift:205:18:205:39 | [...] [Collection element] | CommandInjection.swift:207:18:207:18 | tainted1 [Collection element] | provenance | |
-| CommandInjection.swift:205:18:205:39 | [...] [Collection element] | CommandInjection.swift:208:19:208:19 | tainted1 [Collection element] | provenance | |
-| CommandInjection.swift:205:18:205:39 | [...] [Collection element] | CommandInjection.swift:209:18:209:18 | tainted1 [Collection element] | provenance | |
-| CommandInjection.swift:205:19:205:19 | userControlledString | CommandInjection.swift:205:18:205:39 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:207:18:207:18 | tainted1 [Collection element] | CommandInjection.swift:207:3:207:3 | [post] getter for .p1 | provenance | |
-| CommandInjection.swift:208:19:208:19 | tainted1 [Collection element] | CommandInjection.swift:208:3:208:5 | [post] ...! | provenance | |
-| CommandInjection.swift:209:18:209:18 | tainted1 [Collection element] | CommandInjection.swift:209:3:209:3 | [post] ...! | provenance | |
-| CommandInjection.swift:211:30:211:51 | [...] [Collection element] | CommandInjection.swift:213:18:213:18 | tainted2 [Collection element] | provenance | |
-| CommandInjection.swift:211:30:211:51 | [...] [Collection element] | CommandInjection.swift:214:19:214:19 | tainted2 [Collection element] | provenance | |
-| CommandInjection.swift:211:30:211:51 | [...] [Collection element] | CommandInjection.swift:215:18:215:18 | tainted2 [Collection element] | provenance | |
-| CommandInjection.swift:211:30:211:51 | [...] [Collection element] | CommandInjection.swift:217:13:217:13 | tainted2 [Collection element] | provenance | |
-| CommandInjection.swift:211:31:211:31 | userControlledString | CommandInjection.swift:211:30:211:51 | [...] [Collection element] | provenance | |
-| CommandInjection.swift:213:18:213:18 | tainted2 [Collection element] | CommandInjection.swift:213:3:213:3 | [post] getter for .p1 | provenance | |
-| CommandInjection.swift:214:19:214:19 | tainted2 [Collection element] | CommandInjection.swift:214:3:214:5 | [post] ...! | provenance | |
-| CommandInjection.swift:215:18:215:18 | tainted2 [Collection element] | CommandInjection.swift:215:3:215:3 | [post] ...! | provenance | |
-| CommandInjection.swift:217:13:217:13 | tainted2 [Collection element] | CommandInjection.swift:193:3:193:3 | newValue [Collection element] | provenance | |
-| file://:0:0:0:0 | url | file://:0:0:0:0 | url | provenance | |
-| file://:0:0:0:0 | url | file://:0:0:0:0 | url | provenance | |
+| CommandInjection.swift:105:8:105:31 | ... .some(...) [some.0] | CommandInjection.swift:105:12:105:31 | userControlledString | provenance | |
+| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:150:42:150:61 | userControlledString | provenance | |
+| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:160:53:160:72 | userControlledString | provenance | |
+| CommandInjection.swift:105:35:105:94 | try? ... [some.0] | CommandInjection.swift:105:8:105:31 | ... .some(...) [some.0] | provenance | |
+| CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:105:35:105:94 | try? ... [some.0] | provenance | |
+| CommandInjection.swift:160:53:160:72 | userControlledString | CommandInjection.swift:160:41:160:74 | ... ! | provenance | |
nodes
-| CommandInjection.swift:64:22:64:33 | command | semmle.label | command |
-| CommandInjection.swift:64:22:64:33 | command [some:0] | semmle.label | command [some:0] |
-| CommandInjection.swift:68:16:68:16 | command | semmle.label | command |
-| CommandInjection.swift:68:16:68:16 | command [some:0] | semmle.label | command [some:0] |
-| CommandInjection.swift:68:16:68:16 | command [some:0] | semmle.label | command [some:0] |
-| CommandInjection.swift:75:8:75:12 | let ...? [some:0, some:0] | semmle.label | let ...? [some:0, some:0] |
-| CommandInjection.swift:75:8:75:12 | let ...? [some:0] | semmle.label | let ...? [some:0] |
-| CommandInjection.swift:75:12:75:12 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:75:12:75:12 | userControlledString [some:0] | semmle.label | userControlledString [some:0] |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0, some:0] | semmle.label | call to String.init(contentsOf:) [some:0, some:0] |
-| CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) [some:0] | semmle.label | call to String.init(contentsOf:) [some:0] |
-| CommandInjection.swift:81:2:81:2 | [post] task1 | semmle.label | [post] task1 |
-| CommandInjection.swift:81:20:81:47 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:81:27:81:27 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:84:5:84:9 | let ...? [some:0] | semmle.label | let ...? [some:0] |
-| CommandInjection.swift:84:9:84:9 | validatedString | semmle.label | validatedString |
-| CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) | semmle.label | call to validateCommand(_:) |
-| CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) [some:0] | semmle.label | call to validateCommand(_:) [some:0] |
-| CommandInjection.swift:84:43:84:43 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:84:43:84:43 | userControlledString [some:0] | semmle.label | userControlledString [some:0] |
-| CommandInjection.swift:87:6:87:6 | [post] task2 | semmle.label | [post] task2 |
-| CommandInjection.swift:87:24:87:46 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:87:31:87:31 | validatedString | semmle.label | validatedString |
-| CommandInjection.swift:99:20:99:40 | arguments [Collection element] | semmle.label | arguments [Collection element] |
-| CommandInjection.swift:100:3:100:3 | [post] self | semmle.label | [post] self |
-| CommandInjection.swift:100:20:100:20 | arguments [Collection element] | semmle.label | arguments [Collection element] |
-| CommandInjection.swift:105:8:105:12 | let ...? [some:0] | semmle.label | let ...? [some:0] |
-| CommandInjection.swift:105:12:105:12 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
-| CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) [some:0] | semmle.label | call to String.init(contentsOf:) [some:0] |
-| CommandInjection.swift:120:2:120:2 | [post] task3 | semmle.label | [post] task3 |
-| CommandInjection.swift:120:24:120:56 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:120:24:120:57 | ...! | semmle.label | ...! |
-| CommandInjection.swift:120:36:120:36 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:121:2:121:2 | [post] task3 | semmle.label | [post] task3 |
-| CommandInjection.swift:121:20:121:48 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:121:28:121:28 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:125:2:125:2 | [post] task4 | semmle.label | [post] task4 |
-| CommandInjection.swift:125:24:125:65 | call to URL.init(fileURLWithPath:) | semmle.label | call to URL.init(fileURLWithPath:) |
-| CommandInjection.swift:125:45:125:45 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:126:2:126:2 | [post] task4 | semmle.label | [post] task4 |
-| CommandInjection.swift:126:24:126:56 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:126:24:126:57 | ...! | semmle.label | ...! |
-| CommandInjection.swift:126:36:126:36 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:127:2:127:2 | [post] task4 | semmle.label | [post] task4 |
-| CommandInjection.swift:127:20:127:56 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:127:28:127:36 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
-| CommandInjection.swift:131:2:131:7 | [post] ...? | semmle.label | [post] ...? |
-| CommandInjection.swift:131:25:131:66 | call to URL.init(fileURLWithPath:) | semmle.label | call to URL.init(fileURLWithPath:) |
-| CommandInjection.swift:131:46:131:46 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:132:2:132:7 | [post] ...? | semmle.label | [post] ...? |
-| CommandInjection.swift:132:21:132:42 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:132:22:132:22 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:136:2:136:2 | [post] task6 | semmle.label | [post] task6 |
-| CommandInjection.swift:136:24:136:65 | call to URL.init(fileURLWithPath:) | semmle.label | call to URL.init(fileURLWithPath:) |
-| CommandInjection.swift:136:45:136:45 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:137:2:137:2 | [post] task6 | semmle.label | [post] task6 |
-| CommandInjection.swift:137:24:137:56 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:137:24:137:57 | ...! | semmle.label | ...! |
-| CommandInjection.swift:137:36:137:36 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:138:2:138:2 | [post] task6 | semmle.label | [post] task6 |
-| CommandInjection.swift:138:20:138:41 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:138:21:138:21 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:139:21:139:42 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:139:22:139:22 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:150:42:150:42 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:151:67:151:95 | [...] | semmle.label | [...] |
-| CommandInjection.swift:151:75:151:75 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:154:23:154:55 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:154:23:154:56 | ...! | semmle.label | ...! |
-| CommandInjection.swift:154:35:154:35 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:155:62:155:90 | [...] | semmle.label | [...] |
-| CommandInjection.swift:155:70:155:70 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:160:41:160:73 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:160:41:160:74 | ...! | semmle.label | ...! |
-| CommandInjection.swift:160:53:160:53 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:163:40:163:72 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:163:40:163:73 | ...! | semmle.label | ...! |
-| CommandInjection.swift:163:40:163:73 | ...! | semmle.label | ...! |
-| CommandInjection.swift:163:52:163:52 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:164:32:164:53 | [...] | semmle.label | [...] |
-| CommandInjection.swift:164:33:164:33 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:166:45:166:77 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
-| CommandInjection.swift:166:45:166:78 | ...! | semmle.label | ...! |
-| CommandInjection.swift:166:45:166:78 | ...! | semmle.label | ...! |
-| CommandInjection.swift:166:57:166:57 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:193:3:193:3 | newValue [Collection element] | semmle.label | newValue [Collection element] |
-| CommandInjection.swift:194:4:194:4 | [post] getter for .p1 | semmle.label | [post] getter for .p1 |
-| CommandInjection.swift:194:19:194:19 | newValue [Collection element] | semmle.label | newValue [Collection element] |
-| CommandInjection.swift:195:4:195:6 | [post] ...! | semmle.label | [post] ...! |
-| CommandInjection.swift:195:20:195:20 | newValue [Collection element] | semmle.label | newValue [Collection element] |
-| CommandInjection.swift:196:4:196:4 | [post] ...! | semmle.label | [post] ...! |
-| CommandInjection.swift:196:19:196:19 | newValue [Collection element] | semmle.label | newValue [Collection element] |
-| CommandInjection.swift:201:9:201:13 | let ...? [some:0] | semmle.label | let ...? [some:0] |
-| CommandInjection.swift:201:13:201:13 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
-| CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) [some:0] | semmle.label | call to String.init(contentsOf:) [some:0] |
-| CommandInjection.swift:205:18:205:39 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:205:19:205:19 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:207:3:207:3 | [post] getter for .p1 | semmle.label | [post] getter for .p1 |
-| CommandInjection.swift:207:18:207:18 | tainted1 [Collection element] | semmle.label | tainted1 [Collection element] |
-| CommandInjection.swift:208:3:208:5 | [post] ...! | semmle.label | [post] ...! |
-| CommandInjection.swift:208:19:208:19 | tainted1 [Collection element] | semmle.label | tainted1 [Collection element] |
-| CommandInjection.swift:209:3:209:3 | [post] ...! | semmle.label | [post] ...! |
-| CommandInjection.swift:209:18:209:18 | tainted1 [Collection element] | semmle.label | tainted1 [Collection element] |
-| CommandInjection.swift:211:30:211:51 | [...] [Collection element] | semmle.label | [...] [Collection element] |
-| CommandInjection.swift:211:31:211:31 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:213:3:213:3 | [post] getter for .p1 | semmle.label | [post] getter for .p1 |
-| CommandInjection.swift:213:18:213:18 | tainted2 [Collection element] | semmle.label | tainted2 [Collection element] |
-| CommandInjection.swift:214:3:214:5 | [post] ...! | semmle.label | [post] ...! |
-| CommandInjection.swift:214:19:214:19 | tainted2 [Collection element] | semmle.label | tainted2 [Collection element] |
-| CommandInjection.swift:215:3:215:3 | [post] ...! | semmle.label | [post] ...! |
-| CommandInjection.swift:215:18:215:18 | tainted2 [Collection element] | semmle.label | tainted2 [Collection element] |
-| CommandInjection.swift:217:13:217:13 | tainted2 [Collection element] | semmle.label | tainted2 [Collection element] |
-| file://:0:0:0:0 | url | semmle.label | url |
-| file://:0:0:0:0 | url | semmle.label | url |
-| file://:0:0:0:0 | url | semmle.label | url |
-| file://:0:0:0:0 | url | semmle.label | url |
+| CommandInjection.swift:105:8:105:31 | ... .some(...) [some.0] | semmle.label | ... .some(...) [some.0] |
+| CommandInjection.swift:105:12:105:31 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:105:35:105:94 | try? ... [some.0] | semmle.label | try? ... [some.0] |
+| CommandInjection.swift:105:40:105:94 | String(...) | semmle.label | String(...) |
+| CommandInjection.swift:150:42:150:61 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:160:41:160:74 | ... ! | semmle.label | ... ! |
+| CommandInjection.swift:160:53:160:72 | userControlledString | semmle.label | userControlledString |
subpaths
-| CommandInjection.swift:84:43:84:43 | userControlledString | CommandInjection.swift:64:22:64:33 | command | CommandInjection.swift:68:16:68:16 | command | CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) |
-| CommandInjection.swift:84:43:84:43 | userControlledString | CommandInjection.swift:64:22:64:33 | command | CommandInjection.swift:68:16:68:16 | command [some:0] | CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) [some:0] |
-| CommandInjection.swift:84:43:84:43 | userControlledString [some:0] | CommandInjection.swift:64:22:64:33 | command [some:0] | CommandInjection.swift:68:16:68:16 | command [some:0] | CommandInjection.swift:84:27:84:63 | call to validateCommand(_:) [some:0] |
-#select
-| CommandInjection.swift:81:2:81:2 | [post] task1 | CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | CommandInjection.swift:81:2:81:2 | [post] task1 | This command depends on a $@. | CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:87:6:87:6 | [post] task2 | CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | CommandInjection.swift:87:6:87:6 | [post] task2 | This command depends on a $@. | CommandInjection.swift:75:40:75:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:100:3:100:3 | [post] self | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:100:3:100:3 | [post] self | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:120:2:120:2 | [post] task3 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:120:2:120:2 | [post] task3 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:121:2:121:2 | [post] task3 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:121:2:121:2 | [post] task3 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:125:2:125:2 | [post] task4 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:125:2:125:2 | [post] task4 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:126:2:126:2 | [post] task4 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:126:2:126:2 | [post] task4 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:127:2:127:2 | [post] task4 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:127:2:127:2 | [post] task4 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:131:2:131:7 | [post] ...? | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:131:2:131:7 | [post] ...? | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:132:2:132:7 | [post] ...? | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:132:2:132:7 | [post] ...? | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:136:2:136:2 | [post] task6 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:136:2:136:2 | [post] task6 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:137:2:137:2 | [post] task6 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:137:2:137:2 | [post] task6 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:138:2:138:2 | [post] task6 | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:138:2:138:2 | [post] task6 | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:150:42:150:42 | userControlledString | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:150:42:150:42 | userControlledString | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:151:67:151:95 | [...] | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:151:67:151:95 | [...] | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:154:23:154:56 | ...! | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:154:23:154:56 | ...! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:155:62:155:90 | [...] | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:155:62:155:90 | [...] | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:160:41:160:74 | ...! | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:160:41:160:74 | ...! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:163:40:163:73 | ...! | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:163:40:163:73 | ...! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:164:32:164:53 | [...] | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:164:32:164:53 | [...] | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:166:45:166:78 | ...! | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | CommandInjection.swift:166:45:166:78 | ...! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:194:4:194:4 | [post] getter for .p1 | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:194:4:194:4 | [post] getter for .p1 | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:195:4:195:6 | [post] ...! | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:195:4:195:6 | [post] ...! | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:196:4:196:4 | [post] ...! | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:196:4:196:4 | [post] ...! | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:207:3:207:3 | [post] getter for .p1 | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:207:3:207:3 | [post] getter for .p1 | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:208:3:208:5 | [post] ...! | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:208:3:208:5 | [post] ...! | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:209:3:209:3 | [post] ...! | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:209:3:209:3 | [post] ...! | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:213:3:213:3 | [post] getter for .p1 | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:213:3:213:3 | [post] getter for .p1 | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:214:3:214:5 | [post] ...! | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:214:3:214:5 | [post] ...! | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| CommandInjection.swift:215:3:215:3 | [post] ...! | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | CommandInjection.swift:215:3:215:3 | [post] ...! | This command depends on a $@. | CommandInjection.swift:201:41:201:95 | call to String.init(contentsOf:) | user-provided value |
-| file://:0:0:0:0 | url | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | file://:0:0:0:0 | url | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
-| file://:0:0:0:0 | url | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | file://:0:0:0:0 | url | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | call to String.init(contentsOf:) | user-provided value |
diff --git a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.qlref b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.qlref
index 87be59af70b3..330ea2d5bede 100644
--- a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.qlref
+++ b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.qlref
@@ -1 +1,3 @@
-queries/Security/CWE-078/CommandInjection.ql
\ No newline at end of file
+query: queries/security/CWE-078/CommandInjection.ql
+postprocess:
+ - utils/test/InlineExpectationsTestQuery.ql
\ No newline at end of file
diff --git a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
index 4ef0ac58aed7..e70d80a9dc3b 100644
--- a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
+++ b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
@@ -72,13 +72,13 @@ func validateCommand(_ command: String) -> String? {
}
func testCommandInjectionQhelpExamples() {
- guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else {
+ guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else { // $ MISSING: Source
return
}
let task1 = Process()
task1.launchPath = "/bin/bash" // GOOD
- task1.arguments = ["-c", userControlledString] // BAD
+ task1.arguments = ["-c", userControlledString] // $ MISSING: Alert
task1.launch()
if let validatedString = validateCommand(userControlledString) {
@@ -97,12 +97,12 @@ class MyProcess : Process {
var harmlessField: String?
func setArguments(_ arguments: [String]) {
- self.arguments = arguments // BAD
+ self.arguments = arguments // $ MISSING: Alert
}
}
func testCommandInjectionMore(mySafeString: String) {
- guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else {
+ guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else { // $ Source
return
}
@@ -117,25 +117,25 @@ func testCommandInjectionMore(mySafeString: String) {
try! task2.run()
let task3 = Process()
- task3.executableURL = URL(string: userControlledString)! // BAD
- task3.arguments = ["abc", userControlledString] // BAD
+ task3.executableURL = URL(string: userControlledString)! // $ MISSING: Alert
+ task3.arguments = ["abc", userControlledString] // $ MISSING: Alert
try! task3.run()
let task4 = Process()
- task4.executableURL = URL(fileURLWithPath: userControlledString) // BAD
- task4.executableURL = URL(string: userControlledString)! // BAD
- task4.arguments = ["abc", "def" + userControlledString] // BAD
+ task4.executableURL = URL(fileURLWithPath: userControlledString) // $ MISSING: Alert
+ task4.executableURL = URL(string: userControlledString)! // $ MISSING: Alert
+ task4.arguments = ["abc", "def" + userControlledString] // $ MISSING: Alert
try! task4.run()
let task5 = mkProcess()
- task5?.executableURL = URL(fileURLWithPath: userControlledString) // BAD
- task5?.arguments = [userControlledString] // BAD
+ task5?.executableURL = URL(fileURLWithPath: userControlledString) // $ MISSING: Alert
+ task5?.arguments = [userControlledString] // $ MISSING: Alert
try! task5?.run()
let task6 = MyProcess()
- task6.executableURL = URL(fileURLWithPath: userControlledString) // BAD
- task6.executableURL = URL(string: userControlledString)! // BAD
- task6.arguments = [userControlledString] // BAD
+ task6.executableURL = URL(fileURLWithPath: userControlledString) // $ MISSING: Alert
+ task6.executableURL = URL(string: userControlledString)! // $ MISSING: Alert
+ task6.arguments = [userControlledString] // $ MISSING: Alert
task6.setArguments([userControlledString]) // BAD (flagged inside `setArguments`)
task6.harmlessField = userControlledString // GOOD
try! task6.run()
@@ -143,28 +143,28 @@ func testCommandInjectionMore(mySafeString: String) {
let task7 = Process()
task7.executableURL = URL(fileURLWithPath: mySafeString) // GOOD
task7.arguments = ["abc", "def"]
- task7.arguments?.append(userControlledString) // BAD [NOT DETECTED]
+ task7.arguments?.append(userControlledString) // $ MISSING: Alert // Originally missing
try! task7.run()
_ = Process.launchedProcess(launchPath: mySafeString, arguments: ["abc", mySafeString]) // GOOD
- _ = Process.launchedProcess(launchPath: userControlledString, arguments: ["abc", mySafeString]) // BAD
- _ = Process.launchedProcess(launchPath: mySafeString, arguments: ["abc", userControlledString]) // BAD
+ _ = Process.launchedProcess(launchPath: userControlledString, arguments: ["abc", mySafeString]) // $ Alert
+ _ = Process.launchedProcess(launchPath: mySafeString, arguments: ["abc", userControlledString]) // $ MISSING: Alert
_ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", mySafeString]) // GOOD
- _ = try? Process.run(URL(string: userControlledString)!, arguments: ["abc", mySafeString]) // BAD
- _ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", userControlledString]) // BAD
+ _ = try? Process.run(URL(string: userControlledString)!, arguments: ["abc", mySafeString]) // $ MISSING: Alert
+ _ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", userControlledString]) // $ MISSING: Alert
let task8 = try! NSUserScriptTask(url: URL(string: mySafeString)!) // GOOD
task8.execute()
- let task9 = try! NSUserScriptTask(url: URL(string: userControlledString)!) // BAD
+ let task9 = try! NSUserScriptTask(url: URL(string: userControlledString)!) // $ Alert
task9.execute()
- let task10 = try! NSUserUnixTask(url: URL(string: userControlledString)!) // BAD
- task10.execute(withArguments: [userControlledString]) // BAD
+ let task10 = try! NSUserUnixTask(url: URL(string: userControlledString)!) // $ MISSING: Alert
+ task10.execute(withArguments: [userControlledString]) // $ MISSING: Alert
- let task11 = try! NSUserAutomatorTask(url: URL(string: userControlledString)!) // BAD
- task11.variables = ["abc": userControlledString] // BAD [NOT DETECTED]
+ let task11 = try! NSUserAutomatorTask(url: URL(string: userControlledString)!) // $ MISSING: Alert
+ task11.variables = ["abc": userControlledString] // $ MISSING: Alert // Originally missing
task11.execute(withInput: nil)
let files = try! FileManager.default.contentsOfDirectory(atPath: "some/directory")
@@ -191,28 +191,28 @@ struct MyClass {
return nil
}
set {
- p1.arguments = newValue // BAD
- p2!.arguments = newValue // BAD
- p3.arguments = newValue // BAD
+ p1.arguments = newValue // $ MISSING: Alert
+ p2!.arguments = newValue // $ MISSING: Alert
+ p3.arguments = newValue // $ MISSING: Alert
}
}
mutating func myFunc() {
- guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else {
+ guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else { // $ MISSING: Source
return
}
let tainted1 = [userControlledString]
- p1.arguments = tainted1 // BAD
- p2!.arguments = tainted1 // BAD
- p3.arguments = tainted1 // BAD
+ p1.arguments = tainted1 // $ MISSING: Alert
+ p2!.arguments = tainted1 // $ MISSING: Alert
+ p3.arguments = tainted1 // $ MISSING: Alert
let tainted2 : [String]? = [userControlledString]
- p1.arguments = tainted2 // BAD
- p2!.arguments = tainted2 // BAD
- p3.arguments = tainted2 // BAD
+ p1.arguments = tainted2 // $ MISSING: Alert
+ p2!.arguments = tainted2 // $ MISSING: Alert
+ p3.arguments = tainted2 // $ MISSING: Alert
myValue = tainted2
}
From 618b888aa3d897df67c19bcc5326e3b368be78a3 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 23 Oct 2026 14:35:31 +0100
Subject: [PATCH 4/7] unified: model Process.run with its default termination
handler
Add the model-as-data selector for calls that omit terminationHandler, retaining the existing full-argument model. This detects the previously missing executable-URL case without query-local model code.
Cover explicit and omitted termination handlers with positive and safe cases. The command-injection test now reports four alerts with no expectation failures; both it and the path-injection test pass without --learn.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
unified/ql/lib/ext/legacy-swift.model.yml | 2 ++
.../CommandInjection.expected | 20 ++++++++++++++-----
.../CommandInjection/CommandInjection.swift | 5 ++++-
3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/unified/ql/lib/ext/legacy-swift.model.yml b/unified/ql/lib/ext/legacy-swift.model.yml
index 30d5be429efc..d262fadcec1d 100644
--- a/unified/ql/lib/ext/legacy-swift.model.yml
+++ b/unified/ql/lib/ext/legacy-swift.model.yml
@@ -220,6 +220,8 @@ extensions:
- ["", "Process", true, "executableURL", "", "", "PostUpdate", "command-injection", "manual"]
- ["", "Process", true, "launchPath", "", "", "PostUpdate", "command-injection", "manual"]
- ["", "Process", true, "launchedProcess(arguments:launchPath:)", "", "", "Argument[launchPath:,arguments:]", "command-injection", "manual"]
+ # Calls may omit the defaulted terminationHandler argument.
+ - ["", "Process", true, "run(_:arguments:)", "", "", "Argument[0,arguments:]", "command-injection", "manual"]
- ["", "Process", true, "run(_:arguments:terminationHandler:)", "", "", "Argument[0,arguments:]", "command-injection", "manual"]
- ["", "Process", true, "standardError", "", "", "PostUpdate", "command-injection", "manual"]
- ["", "Process", true, "standardInput", "", "", "PostUpdate", "command-injection", "manual"]
diff --git a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected
index 2a0d50ee5f7d..3d8ffa476377 100644
--- a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected
+++ b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.expected
@@ -1,19 +1,29 @@
#select
| CommandInjection.swift:150:42:150:61 | userControlledString | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:150:42:150:61 | userControlledString | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
-| CommandInjection.swift:160:41:160:74 | ... ! | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:160:41:160:74 | ... ! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
+| CommandInjection.swift:154:23:154:56 | ... ! | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:154:23:154:56 | ... ! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
+| CommandInjection.swift:158:23:158:56 | ... ! | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:158:23:158:56 | ... ! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
+| CommandInjection.swift:163:41:163:74 | ... ! | CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:163:41:163:74 | ... ! | This command depends on a $@. | CommandInjection.swift:105:40:105:94 | String(...) | user-provided value |
edges
| CommandInjection.swift:105:8:105:31 | ... .some(...) [some.0] | CommandInjection.swift:105:12:105:31 | userControlledString | provenance | |
| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:150:42:150:61 | userControlledString | provenance | |
-| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:160:53:160:72 | userControlledString | provenance | |
+| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:154:35:154:54 | userControlledString | provenance | |
+| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:158:35:158:54 | userControlledString | provenance | |
+| CommandInjection.swift:105:12:105:31 | userControlledString | CommandInjection.swift:163:53:163:72 | userControlledString | provenance | |
| CommandInjection.swift:105:35:105:94 | try? ... [some.0] | CommandInjection.swift:105:8:105:31 | ... .some(...) [some.0] | provenance | |
| CommandInjection.swift:105:40:105:94 | String(...) | CommandInjection.swift:105:35:105:94 | try? ... [some.0] | provenance | |
-| CommandInjection.swift:160:53:160:72 | userControlledString | CommandInjection.swift:160:41:160:74 | ... ! | provenance | |
+| CommandInjection.swift:154:35:154:54 | userControlledString | CommandInjection.swift:154:23:154:56 | ... ! | provenance | |
+| CommandInjection.swift:158:35:158:54 | userControlledString | CommandInjection.swift:158:23:158:56 | ... ! | provenance | |
+| CommandInjection.swift:163:53:163:72 | userControlledString | CommandInjection.swift:163:41:163:74 | ... ! | provenance | |
nodes
| CommandInjection.swift:105:8:105:31 | ... .some(...) [some.0] | semmle.label | ... .some(...) [some.0] |
| CommandInjection.swift:105:12:105:31 | userControlledString | semmle.label | userControlledString |
| CommandInjection.swift:105:35:105:94 | try? ... [some.0] | semmle.label | try? ... [some.0] |
| CommandInjection.swift:105:40:105:94 | String(...) | semmle.label | String(...) |
| CommandInjection.swift:150:42:150:61 | userControlledString | semmle.label | userControlledString |
-| CommandInjection.swift:160:41:160:74 | ... ! | semmle.label | ... ! |
-| CommandInjection.swift:160:53:160:72 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:154:23:154:56 | ... ! | semmle.label | ... ! |
+| CommandInjection.swift:154:35:154:54 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:158:23:158:56 | ... ! | semmle.label | ... ! |
+| CommandInjection.swift:158:35:158:54 | userControlledString | semmle.label | userControlledString |
+| CommandInjection.swift:163:41:163:74 | ... ! | semmle.label | ... ! |
+| CommandInjection.swift:163:53:163:72 | userControlledString | semmle.label | userControlledString |
subpaths
diff --git a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
index e70d80a9dc3b..0b9307d10bf5 100644
--- a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
+++ b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
@@ -151,9 +151,12 @@ func testCommandInjectionMore(mySafeString: String) {
_ = Process.launchedProcess(launchPath: mySafeString, arguments: ["abc", userControlledString]) // $ MISSING: Alert
_ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", mySafeString]) // GOOD
- _ = try? Process.run(URL(string: userControlledString)!, arguments: ["abc", mySafeString]) // $ MISSING: Alert
+ _ = try? Process.run(URL(string: userControlledString)!, arguments: ["abc", mySafeString]) // $ Alert
_ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", userControlledString]) // $ MISSING: Alert
+ _ = try? Process.run(URL(string: mySafeString)!, arguments: [], terminationHandler: nil) // GOOD
+ _ = try? Process.run(URL(string: userControlledString)!, arguments: [], terminationHandler: nil) // $ Alert
+
let task8 = try! NSUserScriptTask(url: URL(string: mySafeString)!) // GOOD
task8.execute()
From d93f510fb99d71909bc7d517ff7d2dda17ad79fa Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 23 Oct 2026 14:36:59 +0100
Subject: [PATCH 5/7] unified: refresh command injection guidance and
references
Replace the OWASP link returning 404 with its current canonical page (verified HTTP 200). Explain fixed executables, separate arguments, and allowlisting complete shell commands so the guidance matches the examples.
Clarify which test comments describe original Swift false positives or currently missing alerts. Help XML and example paths validate, and the focused test passes with unchanged results.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../security/CWE-078/CommandInjection.qhelp | 27 ++++++++++---------
.../CommandInjection/CommandInjection.swift | 4 +--
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp b/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp
index ed6a27a4222b..33071a352efb 100644
--- a/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp
+++ b/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp
@@ -5,33 +5,34 @@
-Constructing a system command with unsanitized user input is dangerous,
-since a malicious user may be able to craft input that executes arbitrary code.
+Constructing a system command with unvalidated user input may allow an attacker
+to choose an executable or change the meaning of its arguments. If a command
+string is passed to a shell, malicious input may also execute additional commands.
-If possible, use hard-coded string literals to specify the command to run. Instead of interpreting
-user input directly as command names, examine the input and then choose among hard-coded string
-literals.
+If possible, avoid invoking a shell. Use a fixed executable and pass arguments
+separately using Process. Validate untrusted values against the
+allowed values for the command and its arguments.
-If this is not possible, then add sanitization code to verify that the user input is safe before
-using it.
+If a shell command is required, select from an allowlist of complete, fixed
+commands rather than concatenating untrusted input. Do not rely solely on
+removing shell metacharacters.
-The following example executes code from user input without
-sanitizing it first:
+The following example passes user input to bash -c without
+validating it first:
-If user input is used to construct a command it should be checked
-first. This ensures that the user cannot insert characters that have special
-meanings:
+The following example allows only a fixed set of command strings before
+passing one to the shell:
@@ -39,7 +40,7 @@ meanings:
OWASP:
-Command Injection.
+Command Injection.
diff --git a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
index 0b9307d10bf5..b822e8a258a8 100644
--- a/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
+++ b/unified/ql/test/query-tests/security/CWE-078/CommandInjection/CommandInjection.swift
@@ -84,7 +84,7 @@ func testCommandInjectionQhelpExamples() {
if let validatedString = validateCommand(userControlledString) {
let task2 = Process()
task2.launchPath = "/bin/bash" // GOOD
- task2.arguments = ["-c", validatedString] // GOOD [FALSE POSITIVE]
+ task2.arguments = ["-c", validatedString] // GOOD (original Swift false positive)
task2.launch()
}
}
@@ -136,7 +136,7 @@ func testCommandInjectionMore(mySafeString: String) {
task6.executableURL = URL(fileURLWithPath: userControlledString) // $ MISSING: Alert
task6.executableURL = URL(string: userControlledString)! // $ MISSING: Alert
task6.arguments = [userControlledString] // $ MISSING: Alert
- task6.setArguments([userControlledString]) // BAD (flagged inside `setArguments`)
+ task6.setArguments([userControlledString]) // BAD (expected inside setArguments; currently missing)
task6.harmlessField = userControlledString // GOOD
try! task6.run()
From 21a3e09bf362fd13ecdce08007f3182ad7b725d3 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 23 Oct 2026 17:13:52 +0100
Subject: [PATCH 6/7] unified: Revert most of the changes to the .qhelp (as far
as I can tell they don't really fix anything just rephrase?).
---
.../security/CWE-078/CommandInjection.qhelp | 25 +++++++++----------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp b/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp
index 33071a352efb..9fb39fd64a32 100644
--- a/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp
+++ b/unified/ql/src/queries/security/CWE-078/CommandInjection.qhelp
@@ -5,34 +5,33 @@
-Constructing a system command with unvalidated user input may allow an attacker
-to choose an executable or change the meaning of its arguments. If a command
-string is passed to a shell, malicious input may also execute additional commands.
+Constructing a system command with unsanitized user input is dangerous,
+since a malicious user may be able to craft input that executes arbitrary code.
-If possible, avoid invoking a shell. Use a fixed executable and pass arguments
-separately using Process. Validate untrusted values against the
-allowed values for the command and its arguments.
+If possible, use hard-coded string literals to specify the command to run. Instead of interpreting
+user input directly as command names, examine the input and then choose among hard-coded string
+literals.
-If a shell command is required, select from an allowlist of complete, fixed
-commands rather than concatenating untrusted input. Do not rely solely on
-removing shell metacharacters.
+If this is not possible, then add sanitization code to verify that the user input is safe before
+using it.
-The following example passes user input to bash -c without
-validating it first:
+The following example executes code from user input without
+sanitizing it first:
-The following example allows only a fixed set of command strings before
-passing one to the shell:
+If user input is used to construct a command it should be checked
+first. This ensures that the user cannot insert characters that have special
+meanings:
From 2012a65ef1425940099d466857ed4243928fc63c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 23 Oct 2026 18:30:54 +0100
Subject: [PATCH 7/7] unified: Delete excessive comment.
---
unified/ql/src/queries/security/CWE-078/CommandInjection.ql | 3 ---
1 file changed, 3 deletions(-)
diff --git a/unified/ql/src/queries/security/CWE-078/CommandInjection.ql b/unified/ql/src/queries/security/CWE-078/CommandInjection.ql
index 54a4394dff4f..c1268d2bde21 100644
--- a/unified/ql/src/queries/security/CWE-078/CommandInjection.ql
+++ b/unified/ql/src/queries/security/CWE-078/CommandInjection.ql
@@ -33,9 +33,6 @@ module CommandInjectionConfig implements DataFlow::ConfigSig {
predicate observeDiffInformedIncrementalMode() { any() }
}
-/**
- * Detect taint flow of tainted data that reaches a command injection sink.
- */
module CommandInjectionFlow = TaintTracking::Global;
import CommandInjectionFlow::PathGraph