Skip to content

Commit ade5686

Browse files
authored
Merge pull request #17335 from egregius313/egregius313/go/dataflow/models/stdin
Go: Implement `stdin` models
2 parents 96ea950 + 0abc0d1 commit ade5686

File tree

11 files changed

+125
-0
lines changed

11 files changed

+125
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Local source models with the `stdin` source kind have been added for the variable `os.Stdin` and the functions `fmt.Scan`, `fmt.Scanf` and `fmt.Scanln`. You can optionally include threat models as appropriate when using the CodeQL CLI and in GitHub code scanning. For more information, see [Analyzing your code with CodeQL queries](https://docs.github.com/code-security/codeql-cli/getting-started-with-the-codeql-cli/analyzing-your-code-with-codeql-queries#including-model-packs-to-add-potential-sources-of-tainted-data>) and [Customizing your advanced setup for code scanning](https://docs.github.com/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning#extending-codeql-coverage-with-threat-models).

go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ module Fmt {
112112
Scanner() { this.hasQualifiedName("fmt", ["Scan", "Scanf", "Scanln"]) }
113113
}
114114

115+
private class ScannerSource extends SourceNode {
116+
ScannerSource() {
117+
// All of the arguments which are sources are varargs.
118+
this.asExpr() = any(Scanner s).getACall().getAnImplicitVarargsArgument().asExpr()
119+
}
120+
121+
override string getThreatModel() { result = "stdin" }
122+
}
123+
115124
/**
116125
* The `Fscan` function or one of its variants,
117126
* all of which read from a specified `io.Reader`.

go/ql/lib/semmle/go/frameworks/stdlib/Os.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,12 @@ module Os {
4343
input = inp and output = outp
4444
}
4545
}
46+
47+
private class Stdin extends SourceNode {
48+
Stdin() {
49+
exists(Variable osStdin | osStdin.hasQualifiedName("os", "Stdin") | this = osStdin.getARead())
50+
}
51+
52+
override string getThreatModel() { result = "stdin" }
53+
}
4654
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module test
2+
3+
go 1.22.6
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
testFailures
2+
invalidModelRow
3+
failures
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extensions:
2+
3+
- addsTo:
4+
pack: codeql/threat-models
5+
extensible: threatModelConfiguration
6+
data:
7+
- ["stdin", true, 0]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import go
2+
import ModelValidation
3+
import TestUtilities.InlineExpectationsTest
4+
5+
module SourceTest implements TestSig {
6+
string getARelevantTag() { result = "source" }
7+
8+
predicate hasActualResult(Location location, string element, string tag, string value) {
9+
exists(ActiveThreatModelSource s |
10+
s.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
11+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
12+
element = s.toString() and
13+
value = "" and
14+
tag = "source"
15+
)
16+
}
17+
}
18+
19+
import MakeTest<SourceTest>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
testFailures
2+
invalidModelRow
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extensions:
2+
3+
- addsTo:
4+
pack: codeql/threat-models
5+
extensible: threatModelConfiguration
6+
data:
7+
- ["stdin", true, 0]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package test
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
)
8+
9+
func sink(string) {
10+
11+
}
12+
13+
func readStdinBuffer() {
14+
buf := make([]byte, 1024)
15+
n, err := os.Stdin.Read(buf) // $source
16+
if err != nil {
17+
return
18+
}
19+
sink(string(buf[:n])) // $hasTaintFlow="type conversion"
20+
}
21+
22+
func readStdinBuffReader() {
23+
buf := make([]byte, 1024)
24+
r := bufio.NewReader(os.Stdin) // $source
25+
n, err := r.Read(buf)
26+
if err != nil {
27+
return
28+
}
29+
sink(string(buf[:n])) // $hasTaintFlow="type conversion"
30+
}
31+
32+
func scan() {
33+
var username, email string
34+
fmt.Scan(&username, &email) // $source
35+
sink(username) // $hasTaintFlow="username"
36+
}
37+
38+
func scanf() {
39+
var s string
40+
fmt.Scanf("%s", &s) // $source
41+
sink(s) // $hasTaintFlow="s"
42+
}
43+
44+
func scanl() {
45+
var s string
46+
fmt.Scanln(&s) // $source
47+
sink(s) // $hasTaintFlow="s"
48+
}

0 commit comments

Comments
 (0)