Skip to content

Commit 794409f

Browse files
committed
Make strings.Replacer.WriteString a sanitizer for log injection
1 parent a7da46b commit 794409f

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ module LogInjection {
6969
}
7070
}
7171

72+
/**
73+
* A call to `strings.Replacer.WriteString`, considered as a sanitizer for log
74+
* injection.
75+
*/
76+
class ReplacerWriteStringSanitizer extends Sanitizer {
77+
ReplacerWriteStringSanitizer() {
78+
exists(DataFlow::MethodCallNode call |
79+
call.getTarget().hasQualifiedName("strings", "Replacer", "WriteString") and
80+
this = call.getArgument(1)
81+
)
82+
}
83+
}
84+
7285
/**
7386
* An argument that is formatted using the `%q` directive, considered as a sanitizer
7487
* for log injection.

go/ql/test/query-tests/Security/CWE-117/LogInjection.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package main
1111
//go:generate depstubber -vendor go.uber.org/zap Logger,SugaredLogger NewProduction
1212

1313
import (
14+
"bytes"
1415
"fmt"
1516
"log"
1617
"net/http"
@@ -384,20 +385,35 @@ func handlerGood3(req *http.Request) {
384385
replacer := strings.NewReplacer("\n", "", "\r", "")
385386
log.Printf("user %s logged in.\n", replacer.Replace(username))
386387
log.Printf("user %s logged in.\n", replacerLocal1(username))
388+
log.Printf("user %s logged in.\n", replacerLocal2(username))
387389
log.Printf("user %s logged in.\n", replacerGlobal1(username))
390+
log.Printf("user %s logged in.\n", replacerGlobal2(username))
388391
}
389392

390393
func replacerLocal1(s string) string {
391394
replacer := strings.NewReplacer("\n", "", "\r", "")
392395
return replacer.Replace(s)
393396
}
394397

398+
func replacerLocal2(s string) string {
399+
replacer := strings.NewReplacer("\n", "", "\r", "")
400+
buf := new(bytes.Buffer)
401+
replacer.WriteString(buf, s)
402+
return buf.String()
403+
}
404+
395405
var globalReplacer = strings.NewReplacer("\n", "", "\r", "")
396406

397407
func replacerGlobal1(s string) string {
398408
return globalReplacer.Replace(s)
399409
}
400410

411+
func replacerGlobal2(s string) string {
412+
buf := new(bytes.Buffer)
413+
globalReplacer.WriteString(buf, s)
414+
return buf.String()
415+
}
416+
401417
// GOOD: User-provided values formatted using a %q directive, which escapes newlines
402418
func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) {
403419
username := req.URL.Query()["username"][0]

0 commit comments

Comments
 (0)