Skip to content

Commit 2a45b28

Browse files
authored
Merge pull request #20064 from Kwstubbs/go-path-separator
Update Go Path Injection Sanitizer and Sink
2 parents 7cbaa11 + e2f3c9d commit 2a45b28

File tree

6 files changed

+30
-19
lines changed

6 files changed

+30
-19
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The second argument of the `CreateTemp` function, from the `os` package, is no longer a path-injection sink due to proper sanitization by Go.
5+
* The query "Uncontrolled data used in path expression" (`go/path-injection`) now detects sanitizing a path by adding `os.PathSeparator` or `\` to the beginning.

go/ql/lib/ext/os.model.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ extensions:
2828
- ["os", "", False, "ReadDir", "", "", "Argument[0]", "path-injection", "manual"]
2929
- ["os", "", False, "ReadFile", "", "", "Argument[0]", "path-injection", "manual"]
3030
- ["os", "", False, "MkdirTemp", "", "", "Argument[0..1]", "path-injection", "manual"]
31-
- ["os", "", False, "CreateTemp", "", "", "Argument[0..1]", "path-injection", "manual"]
31+
- ["os", "", False, "CreateTemp", "", "", "Argument[0]", "path-injection", "manual"]
3232
- ["os", "", False, "WriteFile", "", "", "Argument[0]", "path-injection", "manual"]
3333
# command-injection
3434
- ["os", "", False, "StartProcess", "", "", "Argument[0]", "command-injection", "manual"]

go/ql/lib/semmle/go/security/TaintedPathCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ module TaintedPath {
8787
exists(DataFlow::CallNode cleanCall, StringOps::Concatenation concatNode |
8888
cleanCall = any(Function f | f.hasQualifiedName("path/filepath", "Clean")).getACall() and
8989
concatNode = cleanCall.getArgument(0) and
90-
concatNode.getOperand(0).asExpr().(StringLit).getValue() = "/" and
90+
concatNode.getOperand(0).getStringValue().prefix(1) = ["/", "\\"] and
9191
this = cleanCall.getResult()
9292
)
9393
}

go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Os.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
#select
2-
| TaintedPath.go:17:29:17:40 | tainted_path | TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:17:29:17:40 | tainted_path | This path depends on a $@. | TaintedPath.go:14:18:14:22 | selection of URL | user-provided value |
3-
| TaintedPath.go:21:28:21:69 | call to Join | TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:21:28:21:69 | call to Join | This path depends on a $@. | TaintedPath.go:14:18:14:22 | selection of URL | user-provided value |
4-
| TaintedPath.go:68:28:68:57 | call to Clean | TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:68:28:68:57 | call to Clean | This path depends on a $@. | TaintedPath.go:14:18:14:22 | selection of URL | user-provided value |
2+
| TaintedPath.go:18:29:18:40 | tainted_path | TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:18:29:18:40 | tainted_path | This path depends on a $@. | TaintedPath.go:15:18:15:22 | selection of URL | user-provided value |
3+
| TaintedPath.go:22:28:22:69 | call to Join | TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:22:28:22:69 | call to Join | This path depends on a $@. | TaintedPath.go:15:18:15:22 | selection of URL | user-provided value |
4+
| TaintedPath.go:74:28:74:57 | call to Clean | TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:74:28:74:57 | call to Clean | This path depends on a $@. | TaintedPath.go:15:18:15:22 | selection of URL | user-provided value |
55
edges
6-
| TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:14:18:14:30 | call to Query | provenance | Src:MaD:2 MaD:3 |
7-
| TaintedPath.go:14:18:14:30 | call to Query | TaintedPath.go:17:29:17:40 | tainted_path | provenance | Sink:MaD:1 |
8-
| TaintedPath.go:14:18:14:30 | call to Query | TaintedPath.go:21:57:21:68 | tainted_path | provenance | |
9-
| TaintedPath.go:14:18:14:30 | call to Query | TaintedPath.go:68:39:68:56 | ...+... | provenance | |
10-
| TaintedPath.go:21:57:21:68 | tainted_path | TaintedPath.go:21:28:21:69 | call to Join | provenance | FunctionModel Sink:MaD:1 |
11-
| TaintedPath.go:68:39:68:56 | ...+... | TaintedPath.go:68:28:68:57 | call to Clean | provenance | MaD:4 Sink:MaD:1 |
6+
| TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:15:18:15:30 | call to Query | provenance | Src:MaD:2 MaD:3 |
7+
| TaintedPath.go:15:18:15:30 | call to Query | TaintedPath.go:18:29:18:40 | tainted_path | provenance | Sink:MaD:1 |
8+
| TaintedPath.go:15:18:15:30 | call to Query | TaintedPath.go:22:57:22:68 | tainted_path | provenance | |
9+
| TaintedPath.go:15:18:15:30 | call to Query | TaintedPath.go:74:39:74:56 | ...+... | provenance | |
10+
| TaintedPath.go:22:57:22:68 | tainted_path | TaintedPath.go:22:28:22:69 | call to Join | provenance | FunctionModel Sink:MaD:1 |
11+
| TaintedPath.go:74:39:74:56 | ...+... | TaintedPath.go:74:28:74:57 | call to Clean | provenance | MaD:4 Sink:MaD:1 |
1212
models
1313
| 1 | Sink: io/ioutil; ; false; ReadFile; ; ; Argument[0]; path-injection; manual |
1414
| 2 | Source: net/http; Request; true; URL; ; ; ; remote; manual |
1515
| 3 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual |
1616
| 4 | Summary: path; ; false; Clean; ; ; Argument[0]; ReturnValue; taint; manual |
1717
nodes
18-
| TaintedPath.go:14:18:14:22 | selection of URL | semmle.label | selection of URL |
19-
| TaintedPath.go:14:18:14:30 | call to Query | semmle.label | call to Query |
20-
| TaintedPath.go:17:29:17:40 | tainted_path | semmle.label | tainted_path |
21-
| TaintedPath.go:21:28:21:69 | call to Join | semmle.label | call to Join |
22-
| TaintedPath.go:21:57:21:68 | tainted_path | semmle.label | tainted_path |
23-
| TaintedPath.go:68:28:68:57 | call to Clean | semmle.label | call to Clean |
24-
| TaintedPath.go:68:39:68:56 | ...+... | semmle.label | ...+... |
18+
| TaintedPath.go:15:18:15:22 | selection of URL | semmle.label | selection of URL |
19+
| TaintedPath.go:15:18:15:30 | call to Query | semmle.label | call to Query |
20+
| TaintedPath.go:18:29:18:40 | tainted_path | semmle.label | tainted_path |
21+
| TaintedPath.go:22:28:22:69 | call to Join | semmle.label | call to Join |
22+
| TaintedPath.go:22:57:22:68 | tainted_path | semmle.label | tainted_path |
23+
| TaintedPath.go:74:28:74:57 | call to Clean | semmle.label | call to Clean |
24+
| TaintedPath.go:74:39:74:56 | ...+... | semmle.label | ...+... |
2525
subpaths

go/ql/test/query-tests/Security/CWE-022/TaintedPath.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"io/ioutil"
55
"mime/multipart"
66
"net/http"
7+
"os"
78
"path"
89
"path/filepath"
910
"regexp"
@@ -63,6 +64,11 @@ func handler(w http.ResponseWriter, r *http.Request) {
6364
data, _ = ioutil.ReadFile(filepath.Clean("/" + tainted_path))
6465
w.Write(data)
6566

67+
// GOOD: Sanitized by filepath.Clean with a prepended os.PathSeparator forcing interpretation
68+
// as an absolute path, so that Clean will throw away any leading `..` components.
69+
data, _ = ioutil.ReadFile(filepath.Clean(string(os.PathSeparator) + "hardcoded" + tainted_path))
70+
w.Write(data)
71+
6672
// BAD: Sanitized by path.Clean with a prepended '/' forcing interpretation
6773
// as an absolute path, however is not sufficient for Windows paths.
6874
data, _ = ioutil.ReadFile(path.Clean("/" + tainted_path))

0 commit comments

Comments
 (0)