Skip to content

Commit f49ff27

Browse files
authored
Merge pull request github#375 from owen-mc/spew
Model Spew logging framework
2 parents 2b07e6a + b89775a commit f49ff27

File tree

9 files changed

+219
-0
lines changed

9 files changed

+219
-0
lines changed

change-notes/2020-10-14-spew.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added support for the Spew deep pretty-printing framework. This may cause the `go/clear-text-logging` query to return more results when sensitive data is exposed using this library.

ql/src/go.qll

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import semmle.go.frameworks.Macaron
3939
import semmle.go.frameworks.Mux
4040
import semmle.go.frameworks.NoSQL
4141
import semmle.go.frameworks.Protobuf
42+
import semmle.go.frameworks.Spew
4243
import semmle.go.frameworks.SQL
4344
import semmle.go.frameworks.Stdlib
4445
import semmle.go.frameworks.SystemCommandExecutors

ql/src/semmle/go/frameworks/Spew.qll

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Provides models of commonly used functions in the `github.com/davecgh/go-spew/spew` package.
3+
*/
4+
5+
import go
6+
7+
/**
8+
* Provides models of commonly used functions in the `github.com/davecgh/go-spew/spew` package.
9+
*/
10+
module Spew {
11+
private string packagePath() { result = "github.com/davecgh/go-spew/spew" }
12+
13+
private class SpewCall extends LoggerCall::Range, DataFlow::CallNode {
14+
int firstPrintedArg;
15+
16+
SpewCall() {
17+
exists(string fn |
18+
fn in ["Dump", "Errorf", "Print", "Printf", "Println"] and firstPrintedArg = 0
19+
or
20+
fn in ["Fdump", "Fprint", "Fprintf", "Fprintln"] and firstPrintedArg = 1
21+
|
22+
this.getTarget().hasQualifiedName(packagePath(), fn)
23+
)
24+
}
25+
26+
override DataFlow::Node getAMessageComponent() {
27+
result = this.getArgument(any(int i | i >= firstPrintedArg))
28+
}
29+
}
30+
31+
/** The `Sprint` function or one of its variants. */
32+
class Sprinter extends TaintTracking::FunctionModel {
33+
Sprinter() { hasQualifiedName(packagePath(), ["Sdump", "Sprint", "Sprintln", "Sprintf"]) }
34+
35+
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
36+
inp.isParameter(_) and outp.isResult()
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:33:14:33:23 | sUntrusted |
2+
| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:35:14:35:23 | sUntrusted |
3+
| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:41:18:41:27 | sUntrusted |
4+
| test.go:26:16:26:35 | call to getUntrustedString : string | test.go:51:13:51:16 | str3 |
5+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:30:12:30:21 | pUntrusted |
6+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:31:13:31:22 | pUntrusted |
7+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:32:15:32:24 | pUntrusted |
8+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:34:17:34:26 | pUntrusted |
9+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:36:17:36:26 | pUntrusted |
10+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:38:16:38:25 | pUntrusted |
11+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:39:17:39:26 | pUntrusted |
12+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:40:19:40:28 | pUntrusted |
13+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:42:21:42:30 | pUntrusted |
14+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:45:13:45:16 | str1 |
15+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:48:13:48:16 | str2 |
16+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:54:13:54:16 | str4 |
17+
| test.go:28:16:28:35 | call to getUntrustedStruct : Person | test.go:57:13:57:16 | str5 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import go
2+
3+
class UntrustedFunction extends Function {
4+
UntrustedFunction() { this.getName() = ["getUntrustedString", "getUntrustedStruct"] }
5+
}
6+
7+
class UntrustedSource extends DataFlow::Node, UntrustedFlowSource::Range {
8+
UntrustedSource() { this = any(UntrustedFunction f).getACall() }
9+
}
10+
11+
class SinkFunction extends Function {
12+
SinkFunction() { this.getName() = "sinkString" }
13+
}
14+
15+
class TestConfig extends TaintTracking::Configuration {
16+
TestConfig() { this = "testconfig" }
17+
18+
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
19+
20+
override predicate isSink(DataFlow::Node sink) {
21+
sink = any(SinkFunction f).getACall().getAnArgument() or
22+
sink = any(LoggerCall log).getAMessageComponent()
23+
}
24+
}
25+
26+
from TaintTracking::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
27+
where config.hasFlowPath(source, sink)
28+
select source, sink
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module codeql-go-tests/frameworks/Spew
2+
3+
go 1.14
4+
5+
require (
6+
github.com/davecgh/go-spew v1.1.1
7+
github.com/github/depstubber v0.0.0-20200916130315-f3217697abd4 // indirect
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package main
2+
3+
//go:generate depstubber -vendor github.com/davecgh/go-spew/spew "" Dump,Print,Println,Fdump,Fprint,Fprintln,Errorf,Fprintf,Printf,Sdump,Sprint,Sprintf,Sprintln
4+
5+
import (
6+
"io"
7+
8+
"github.com/davecgh/go-spew/spew"
9+
)
10+
11+
func main() {}
12+
13+
type Person struct {
14+
Name string
15+
Address string
16+
}
17+
18+
func getUntrustedString() string { return "%v" }
19+
20+
func getUntrustedStruct() Person { return Person{} }
21+
22+
func sinkString(s string) {}
23+
24+
func testSpew(w io.Writer) {
25+
s := "%v"
26+
sUntrusted := getUntrustedString()
27+
p := Person{}
28+
pUntrusted := getUntrustedStruct()
29+
30+
spew.Dump(pUntrusted) // NOT OK
31+
spew.Print(pUntrusted) // NOT OK
32+
spew.Println(pUntrusted) // NOT OK
33+
spew.Errorf(sUntrusted, p) // NOT OK
34+
spew.Errorf(s, pUntrusted) // NOT OK
35+
spew.Printf(sUntrusted, p) // NOT OK
36+
spew.Printf(s, pUntrusted) // NOT OK
37+
38+
spew.Fdump(w, pUntrusted) // NOT OK
39+
spew.Fprint(w, pUntrusted) // NOT OK
40+
spew.Fprintln(w, pUntrusted) // NOT OK
41+
spew.Fprintf(w, sUntrusted, p) // NOT OK
42+
spew.Fprintf(w, s, pUntrusted) // NOT OK
43+
44+
str1 := spew.Sdump(pUntrusted)
45+
sinkString(str1) // NOT OK
46+
47+
str2 := spew.Sprint(pUntrusted)
48+
sinkString(str2) // NOT OK
49+
50+
str3 := spew.Sprintf(sUntrusted, p)
51+
sinkString(str3) // NOT OK
52+
53+
str4 := spew.Sprintf(s, pUntrusted)
54+
sinkString(str4) // NOT OK
55+
56+
str5 := spew.Sprintln(pUntrusted)
57+
sinkString(str5) // NOT OK
58+
}

ql/test/library-tests/semmle/go/frameworks/Spew/vendor/github.com/davecgh/go-spew/spew/stub.go

+60
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# github.com/davecgh/go-spew v1.1.1
2+
## explicit
3+
github.com/davecgh/go-spew
4+
# github.com/github/depstubber v0.0.0-20200916130315-f3217697abd4
5+
## explicit
6+
github.com/github/depstubber

0 commit comments

Comments
 (0)