mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Swift: Add tests.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
edges
|
||||
| CommandInjection.swift:38:22:38:33 | command | CommandInjection.swift:42:16:42:16 | command |
|
||||
| CommandInjection.swift:38:22:38:33 | command [some:0] | CommandInjection.swift:42:16:42:16 | command [some:0] |
|
||||
| CommandInjection.swift:42:16:42:16 | command | CommandInjection.swift:42:16:42:16 | command [some:0] |
|
||||
| CommandInjection.swift:49:8:49:12 | let ...? [some:0, some:0] | CommandInjection.swift:49:12:49:12 | userControlledString [some:0] |
|
||||
| CommandInjection.swift:49:8:49:12 | let ...? [some:0] | CommandInjection.swift:49:12:49:12 | userControlledString |
|
||||
| CommandInjection.swift:49:12:49:12 | userControlledString | CommandInjection.swift:55:27:55:27 | userControlledString |
|
||||
| CommandInjection.swift:49:12:49:12 | userControlledString | CommandInjection.swift:58:43:58:43 | userControlledString |
|
||||
| CommandInjection.swift:49:12:49:12 | userControlledString [some:0] | CommandInjection.swift:58:43:58:43 | userControlledString [some:0] |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) | CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0] |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0, some:0] | CommandInjection.swift:49:8:49:12 | let ...? [some:0, some:0] |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:49:8:49:12 | let ...? [some:0] |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0, some:0] |
|
||||
| CommandInjection.swift:58:5:58:9 | let ...? [some:0] | CommandInjection.swift:58:9:58:9 | validatedString |
|
||||
| CommandInjection.swift:58:9:58:9 | validatedString | CommandInjection.swift:61:31:61:31 | validatedString |
|
||||
| CommandInjection.swift:58:27:58:63 | call to validateCommand(_:) [some:0] | CommandInjection.swift:58:5:58:9 | let ...? [some:0] |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString | CommandInjection.swift:38:22:38:33 | command |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString | CommandInjection.swift:58:27:58:63 | call to validateCommand(_:) [some:0] |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString [some:0] | CommandInjection.swift:38:22:38:33 | command [some:0] |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString [some:0] | CommandInjection.swift:58:27:58:63 | call to validateCommand(_:) [some:0] |
|
||||
| CommandInjection.swift:79:8:79:12 | let ...? [some:0] | CommandInjection.swift:79:12:79:12 | userControlledString |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | CommandInjection.swift:94:36:94:36 | userControlledString |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | CommandInjection.swift:95:28:95:28 | userControlledString |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | CommandInjection.swift:99:45:99:45 | userControlledString |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | CommandInjection.swift:100:28:100:36 | ... .+(_:_:) ... |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | CommandInjection.swift:104:46:104:46 | userControlledString |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | CommandInjection.swift:105:22:105:22 | userControlledString |
|
||||
| CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) [some:0] |
|
||||
| CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) [some:0] | CommandInjection.swift:79:8:79:12 | let ...? [some:0] |
|
||||
| CommandInjection.swift:94:24:94:56 | call to URL.init(string:) | CommandInjection.swift:94:24:94:56 | call to URL.init(string:) [some:0] |
|
||||
| CommandInjection.swift:94:24:94:56 | call to URL.init(string:) | CommandInjection.swift:94:24:94:57 | ...! |
|
||||
| CommandInjection.swift:94:24:94:56 | call to URL.init(string:) [some:0] | CommandInjection.swift:94:24:94:57 | ...! |
|
||||
| CommandInjection.swift:94:36:94:36 | userControlledString | CommandInjection.swift:94:24:94:56 | call to URL.init(string:) |
|
||||
| CommandInjection.swift:99:45:99:45 | userControlledString | CommandInjection.swift:99:24:99:65 | call to URL.init(fileURLWithPath:) |
|
||||
| CommandInjection.swift:104:46:104:46 | userControlledString | CommandInjection.swift:104:25:104:66 | call to URL.init(fileURLWithPath:) |
|
||||
nodes
|
||||
| CommandInjection.swift:38:22:38:33 | command | semmle.label | command |
|
||||
| CommandInjection.swift:38:22:38:33 | command [some:0] | semmle.label | command [some:0] |
|
||||
| CommandInjection.swift:42:16:42:16 | command | semmle.label | command |
|
||||
| CommandInjection.swift:42:16:42:16 | command [some:0] | semmle.label | command [some:0] |
|
||||
| CommandInjection.swift:42:16:42:16 | command [some:0] | semmle.label | command [some:0] |
|
||||
| CommandInjection.swift:49:8:49:12 | let ...? [some:0, some:0] | semmle.label | let ...? [some:0, some:0] |
|
||||
| CommandInjection.swift:49:8:49:12 | let ...? [some:0] | semmle.label | let ...? [some:0] |
|
||||
| CommandInjection.swift:49:12:49:12 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:49:12:49:12 | userControlledString [some:0] | semmle.label | userControlledString [some:0] |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0, some:0] | semmle.label | call to String.init(contentsOf:) [some:0, some:0] |
|
||||
| CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) [some:0] | semmle.label | call to String.init(contentsOf:) [some:0] |
|
||||
| CommandInjection.swift:55:27:55:27 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:58:5:58:9 | let ...? [some:0] | semmle.label | let ...? [some:0] |
|
||||
| CommandInjection.swift:58:9:58:9 | validatedString | semmle.label | validatedString |
|
||||
| CommandInjection.swift:58:27:58:63 | call to validateCommand(_:) [some:0] | semmle.label | call to validateCommand(_:) [some:0] |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString [some:0] | semmle.label | userControlledString [some:0] |
|
||||
| CommandInjection.swift:61:31:61:31 | validatedString | semmle.label | validatedString |
|
||||
| CommandInjection.swift:79:8:79:12 | let ...? [some:0] | semmle.label | let ...? [some:0] |
|
||||
| CommandInjection.swift:79:12:79:12 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
|
||||
| CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) [some:0] | semmle.label | call to String.init(contentsOf:) [some:0] |
|
||||
| CommandInjection.swift:94:24:94:56 | call to URL.init(string:) | semmle.label | call to URL.init(string:) |
|
||||
| CommandInjection.swift:94:24:94:56 | call to URL.init(string:) [some:0] | semmle.label | call to URL.init(string:) [some:0] |
|
||||
| CommandInjection.swift:94:24:94:57 | ...! | semmle.label | ...! |
|
||||
| CommandInjection.swift:94:36:94:36 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:95:28:95:28 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:99:24:99:65 | call to URL.init(fileURLWithPath:) | semmle.label | call to URL.init(fileURLWithPath:) |
|
||||
| CommandInjection.swift:99:45:99:45 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:100:28:100:36 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
|
||||
| CommandInjection.swift:104:25:104:66 | call to URL.init(fileURLWithPath:) | semmle.label | call to URL.init(fileURLWithPath:) |
|
||||
| CommandInjection.swift:104:46:104:46 | userControlledString | semmle.label | userControlledString |
|
||||
| CommandInjection.swift:105:22:105:22 | userControlledString | semmle.label | userControlledString |
|
||||
subpaths
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString | CommandInjection.swift:38:22:38:33 | command | CommandInjection.swift:42:16:42:16 | command [some:0] | CommandInjection.swift:58:27:58:63 | call to validateCommand(_:) [some:0] |
|
||||
| CommandInjection.swift:58:43:58:43 | userControlledString [some:0] | CommandInjection.swift:38:22:38:33 | command [some:0] | CommandInjection.swift:42:16:42:16 | command [some:0] | CommandInjection.swift:58:27:58:63 | call to validateCommand(_:) [some:0] |
|
||||
#select
|
||||
| CommandInjection.swift:55:27:55:27 | userControlledString | CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) | CommandInjection.swift:55:27:55:27 | userControlledString | This command depends on a $@. | CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:61:31:61:31 | validatedString | CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) | CommandInjection.swift:61:31:61:31 | validatedString | This command depends on a $@. | CommandInjection.swift:49:40:49:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:94:24:94:57 | ...! | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:94:24:94:57 | ...! | This command depends on a $@. | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:95:28:95:28 | userControlledString | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:95:28:95:28 | userControlledString | This command depends on a $@. | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:99:24:99:65 | call to URL.init(fileURLWithPath:) | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:99:24:99:65 | call to URL.init(fileURLWithPath:) | This command depends on a $@. | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:100:28:100:36 | ... .+(_:_:) ... | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:100:28:100:36 | ... .+(_:_:) ... | This command depends on a $@. | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:104:25:104:66 | call to URL.init(fileURLWithPath:) | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:104:25:104:66 | call to URL.init(fileURLWithPath:) | This command depends on a $@. | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
| CommandInjection.swift:105:22:105:22 | userControlledString | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | CommandInjection.swift:105:22:105:22 | userControlledString | This command depends on a $@. | CommandInjection.swift:79:40:79:94 | call to String.init(contentsOf:) | user-provided value |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE-078/CommandInjection.ql
|
||||
@@ -0,0 +1,128 @@
|
||||
|
||||
// --- stubs ---
|
||||
|
||||
struct URL
|
||||
{
|
||||
init?(string: String) {}
|
||||
init(fileURLWithPath: String) {}
|
||||
}
|
||||
|
||||
class NSObject {
|
||||
}
|
||||
|
||||
class Process : NSObject {
|
||||
var launchPath: String? { get { nil } set {} }
|
||||
var arguments: [String]? { get { nil } set {} }
|
||||
func launch() {}
|
||||
|
||||
var executableURL: URL? { get { nil } set {} }
|
||||
func run() throws {}
|
||||
|
||||
class func launchedProcess(launchPath path: String, arguments: [String]) -> Process {
|
||||
return Process()
|
||||
}
|
||||
|
||||
class func run(_ url: URL, arguments: [String], terminationHandler: (@Sendable (Process) -> Void)? = nil) throws -> Process {
|
||||
return Process()
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
init(contentsOf url: URL) throws {
|
||||
self.init("")
|
||||
}
|
||||
}
|
||||
|
||||
// --- tests ---
|
||||
|
||||
func validateCommand(_ command: String) -> String? {
|
||||
let allowedCommands = ["ls -l", "pwd", "echo"]
|
||||
|
||||
if allowedCommands.contains(command) {
|
||||
return command
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testCommandInjectionQhelpExamples() {
|
||||
guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else {
|
||||
return
|
||||
}
|
||||
|
||||
let task1 = Process()
|
||||
task1.launchPath = "/bin/bash" // GOOD
|
||||
task1.arguments = ["-c", userControlledString] // BAD
|
||||
task1.launch()
|
||||
|
||||
if let validatedString = validateCommand(userControlledString) {
|
||||
let task2 = Process()
|
||||
task2.launchPath = "/bin/bash" // GOOD
|
||||
task2.arguments = ["-c", validatedString] // GOOD [FALSE POSITIVE]
|
||||
task2.launch()
|
||||
}
|
||||
}
|
||||
|
||||
func mkProcess() -> Process? {
|
||||
return Process()
|
||||
}
|
||||
|
||||
class MyProcess : Process {
|
||||
var harmlessField: String?
|
||||
|
||||
func setArguments(_ arguments: [String]) {
|
||||
self.arguments = arguments
|
||||
}
|
||||
}
|
||||
|
||||
func testCommandInjectionMore(mySafeString: String) {
|
||||
guard let userControlledString = try? String(contentsOf: URL(string: "http://example.com/")!) else {
|
||||
return
|
||||
}
|
||||
|
||||
let task1 = Process()
|
||||
task1.executableURL = URL(string: mySafeString)! // GOOD
|
||||
task1.arguments = ["abc"] // GOOD
|
||||
try! task1.run()
|
||||
|
||||
let task2 = Process()
|
||||
task2.executableURL = URL(fileURLWithPath: mySafeString) // GOOD
|
||||
task2.arguments = ["abc", "def"] // GOOD
|
||||
try! task2.run()
|
||||
|
||||
let task3 = Process()
|
||||
task3.executableURL = URL(string: userControlledString)! // BAD
|
||||
task3.arguments = ["abc", userControlledString] // BAD
|
||||
try! task3.run()
|
||||
|
||||
let task4 = Process()
|
||||
task4.executableURL = URL(fileURLWithPath: userControlledString) // BAD
|
||||
task4.arguments = ["abc", "def" + userControlledString] // BAD
|
||||
try! task4.run()
|
||||
|
||||
let task5 = mkProcess()
|
||||
task5?.executableURL = URL(fileURLWithPath: userControlledString) // BAD
|
||||
task5?.arguments = [userControlledString] // BAD
|
||||
try! task5?.run()
|
||||
|
||||
let task6 = MyProcess()
|
||||
task6.executableURL = URL(string: userControlledString)! // BAD [NOT DETECTED]
|
||||
task6.arguments = [userControlledString] // BAD [NOT DETECTED]
|
||||
task6.setArguments([userControlledString]) // BAD [NOT DETECTED]
|
||||
task6.harmlessField = userControlledString // GOOD
|
||||
try! task6.run()
|
||||
|
||||
let task7 = Process()
|
||||
task7.executableURL = URL(fileURLWithPath: mySafeString) // GOOD
|
||||
task7.arguments = ["abc", "def"]
|
||||
task7.arguments?.append(userControlledString) // BAD [NOT DETECTED]
|
||||
try! task7.run()
|
||||
|
||||
_ = Process.launchedProcess(launchPath: mySafeString, arguments: ["abc", mySafeString]) // GOOD
|
||||
_ = Process.launchedProcess(launchPath: userControlledString, arguments: ["abc", mySafeString]) // BAD [NOT DETECTED]
|
||||
_ = Process.launchedProcess(launchPath: mySafeString, arguments: ["abc", userControlledString]) // BAD [NOT DETECTED]
|
||||
|
||||
_ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", mySafeString]) // GOOD
|
||||
_ = try? Process.run(URL(string: userControlledString)!, arguments: ["abc", mySafeString]) // BAD [NOT DETECTED]
|
||||
_ = try? Process.run(URL(string: mySafeString)!, arguments: ["abc", userControlledString]) // BAD [NOT DETECTED]
|
||||
}
|
||||
Reference in New Issue
Block a user