Skip to content

Commit bf023b0

Browse files
committed
Use dominance in path injection sanitizer to avoid FNs
1 parent 52ebf66 commit bf023b0

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
/** Provides classes and predicates to reason about path injection vulnerabilities. */
22

33
import swift
4+
private import codeql.swift.controlflow.BasicBlocks
5+
private import codeql.swift.controlflow.ControlFlowGraph
46
private import codeql.swift.dataflow.DataFlow
57
private import codeql.swift.dataflow.ExternalFlow
68
private import codeql.swift.dataflow.TaintTracking
9+
private import codeql.swift.generated.ParentChild
710
private import codeql.swift.frameworks.StandardLibrary.FilePath
811

912
/** A data flow sink for path injection vulnerabilities. */
@@ -32,16 +35,23 @@ private class DefaultPathInjectionSink extends PathInjectionSink {
3235

3336
private class DefaultPathInjectionSanitizer extends PathInjectionSanitizer {
3437
DefaultPathInjectionSanitizer() {
35-
// This is a simple implementation prone to FNs by sanitizing too many nodes.
38+
// This is a simplified implementation.
3639
// TODO: Implement a complete path sanitizer when Guards are available.
37-
exists(CallExpr starts, CallExpr normalize |
40+
exists(CallExpr starts, CallExpr normalize, DataFlow::Node validated |
3841
starts.getStaticTarget().getName() = "starts(with:)" and
3942
starts.getStaticTarget().getEnclosingDecl() instanceof FilePath and
4043
normalize.getStaticTarget().getName() = "lexicallyNormalized()" and
4144
normalize.getStaticTarget().getEnclosingDecl() instanceof FilePath
4245
|
43-
TaintTracking::localTaint(this, DataFlow::exprNode(normalize.getQualifier())) and
44-
DataFlow::localExprFlow(normalize, starts.getQualifier())
46+
TaintTracking::localTaint(validated, DataFlow::exprNode(normalize.getQualifier())) and
47+
DataFlow::localExprFlow(normalize, starts.getQualifier()) and
48+
DataFlow::localFlow(validated, this) and
49+
exists(ConditionBlock bb, SuccessorTypes::BooleanSuccessor b |
50+
bb.getANode().getNode().asAstNode().(IfStmt).getACondition() = getImmediateParent*(starts) and
51+
b.getValue() = true
52+
|
53+
bb.controls(this.getCfgNode().getBasicBlock(), b)
54+
)
4555
)
4656
}
4757
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,5 +196,5 @@ func testSanitizers() {
196196
if (filePath.lexicallyNormalized().starts(with: FilePath(stringLiteral: "/safe"))) {
197197
fm.contents(atPath: remoteString) // Safe
198198
}
199-
fm.contents(atPath: remoteString) // $ MISSING: $ hasPathInjection=191
199+
fm.contents(atPath: remoteString) // $ hasPathInjection=191
200200
}

0 commit comments

Comments
 (0)