Skip to content

Commit 5a09a32

Browse files
committed
Swift: Add heuristic path injection sinks.
1 parent ebf7231 commit 5a09a32

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,41 @@ private class EnumConstructorPathInjectionSink extends PathInjectionSink {
6161
}
6262
}
6363

64+
/**
65+
* A string that might be a label for a path argument.
66+
*/
67+
pragma[inline]
68+
private predicate pathLikeHeuristic(string label) {
69+
label =
70+
[
71+
"atFile", "atPath", "atDirectory", "toFile", "toPath", "toDirectory", "inFile", "inPath",
72+
"inDirectory", "contentsOfFile", "contentsOfPath", "contentsOfDirectory", "filePath",
73+
"directory", "directoryPath"
74+
]
75+
}
76+
77+
/**
78+
* A path injection sink that is determined by imprecise methods.
79+
*/
80+
private class HeuristicPathInjectionSink extends PathInjectionSink {
81+
HeuristicPathInjectionSink() {
82+
// by parameter name
83+
exists(CallExpr ce, int ix, ParamDecl pd |
84+
pathLikeHeuristic(pragma[only_bind_into](pd.getName())) and
85+
pd.getType().getUnderlyingType().getName() = ["String", "NSString"] and
86+
pd = ce.getStaticTarget().getParam(ix) and
87+
this.asExpr() = ce.getArgument(ix).getExpr()
88+
)
89+
or
90+
// by argument name
91+
exists(Argument a |
92+
pathLikeHeuristic(pragma[only_bind_into](a.getLabel())) and
93+
a.getExpr().getType().getUnderlyingType().getName() = ["String", "NSString"] and
94+
this.asExpr() = a.getExpr()
95+
)
96+
}
97+
}
98+
6499
private class DefaultPathInjectionBarrier extends PathInjectionBarrier {
65100
DefaultPathInjectionBarrier() {
66101
// This is a simplified implementation.

swift/ql/test/query-tests/Security/CWE-022/testPathInjection.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ func testPathInjection2(s1: UnsafeMutablePointer<String>, s2: UnsafeMutablePoint
452452
u1.appendPathComponent(remoteString)
453453
_ = NSData(contentsOf: u1) // $ hasPathInjection=445
454454

455-
let u2 = URL(filePath: remoteString)
455+
let u2 = URL(filePath: remoteString) // $ hasPathInjection=445
456456
_ = NSData(contentsOf: u2) // $ hasPathInjection=445
457457

458458
let u3 = NSURL(string: "")!
@@ -504,13 +504,13 @@ class MyFile {
504504
func testPathInjectionHeuristics() {
505505
let remoteString = String(contentsOf: URL(string: "http://example.com/")!)
506506

507-
myOpenFile1(atPath: remoteString) // $ MISSING: hasPathInjection=
508-
myOpenFile2(remoteString) // $ MISSING: hasPathInjection=
509-
myFindFiles(ofType: 0, inDirectory: remoteString) // $ MISSING: hasPathInjection=
507+
myOpenFile1(atPath: remoteString) // $ hasPathInjection=505
508+
myOpenFile2(remoteString) // $ hasPathInjection=505
509+
myFindFiles(ofType: 0, inDirectory: remoteString) // $ hasPathInjection=505
510510

511-
let mc = MyClass(contentsOfFile: remoteString) // $ MISSING: hasPathInjection=
511+
let mc = MyClass(contentsOfFile: remoteString) // $ hasPathInjection=505
512512
mc.doSomething(keyPath: remoteString) // good - not a path
513-
mc.write(toFile: remoteString) // $ MISSING: hasPathInjection=
513+
mc.write(toFile: remoteString) // $ hasPathInjection=505
514514

515515
let mf1 = MyFile(path: "")
516516
let mf2 = MyFile(path: remoteString) // $ MISSING: hasPathInjection=

0 commit comments

Comments
 (0)