From 0e2a61899ae9df746b208b631b7bd17eba19c0db Mon Sep 17 00:00:00 2001 From: Adam Kaplan Date: Sat, 25 Nov 2023 17:51:38 -0500 Subject: [PATCH] chore: Refactor Sample Code to Separate Files Split the code in `source.go` to individual sample files, one per rule. This will help contributors submit samples for new rules, or improvements to existing rules. The cgo sample was all that was left after refactoring, which resulted in its own sample file. Sample code was also formatted to have some level of consistency. Each sample go "file" attempts to keep the formatting of `gofmt`, and each code sample is in its own section in the sample file. Signed-off-by: Adam Kaplan --- testutils/cgo_samples.go | 52 + testutils/g101_samples.go | 348 ++++ testutils/g102_samples.go | 106 + testutils/g103_samples.go | 67 + testutils/g104_samples.go | 227 +++ testutils/g106_samples.go | 20 + testutils/g107_samples.go | 198 ++ testutils/g108_samples.go | 42 + testutils/g109_samples.go | 114 ++ testutils/g110_samples.go | 128 ++ testutils/g111_samples.go | 29 + testutils/g112_samples.go | 107 + testutils/g113_samples.go | 24 + testutils/g114_samples.go | 73 + testutils/g201_samples.go | 403 ++++ testutils/g202_samples.go | 284 +++ testutils/g203_samples.go | 92 + testutils/g204_samples.go | 246 +++ testutils/g301_samples.go | 56 + testutils/g302_samples.go | 73 + testutils/g303_samples.go | 61 + testutils/g304_samples.go | 307 +++ testutils/g305_samples.go | 178 ++ testutils/g306_samples.go | 58 + testutils/g307_samples.go | 49 + testutils/g401_samples.go | 69 + testutils/g402_samples.go | 298 +++ testutils/g403_samples.go | 27 + testutils/g404_samples.go | 104 + testutils/g501_samples.go | 24 + testutils/g502_samples.go | 37 + testutils/g503_samples.go | 29 + testutils/g504_samples.go | 21 + testutils/g505_samples.go | 24 + testutils/g601_samples.go | 221 ++ testutils/g602_samples.go | 255 +++ testutils/sample_types.go | 10 + testutils/source.go | 4076 ------------------------------------- 38 files changed, 4461 insertions(+), 4076 deletions(-) create mode 100644 testutils/cgo_samples.go create mode 100644 testutils/g101_samples.go create mode 100644 testutils/g102_samples.go create mode 100644 testutils/g103_samples.go create mode 100644 testutils/g104_samples.go create mode 100644 testutils/g106_samples.go create mode 100644 testutils/g107_samples.go create mode 100644 testutils/g108_samples.go create mode 100644 testutils/g109_samples.go create mode 100644 testutils/g110_samples.go create mode 100644 testutils/g111_samples.go create mode 100644 testutils/g112_samples.go create mode 100644 testutils/g113_samples.go create mode 100644 testutils/g114_samples.go create mode 100644 testutils/g201_samples.go create mode 100644 testutils/g202_samples.go create mode 100644 testutils/g203_samples.go create mode 100644 testutils/g204_samples.go create mode 100644 testutils/g301_samples.go create mode 100644 testutils/g302_samples.go create mode 100644 testutils/g303_samples.go create mode 100644 testutils/g304_samples.go create mode 100644 testutils/g305_samples.go create mode 100644 testutils/g306_samples.go create mode 100644 testutils/g307_samples.go create mode 100644 testutils/g401_samples.go create mode 100644 testutils/g402_samples.go create mode 100644 testutils/g403_samples.go create mode 100644 testutils/g404_samples.go create mode 100644 testutils/g501_samples.go create mode 100644 testutils/g502_samples.go create mode 100644 testutils/g503_samples.go create mode 100644 testutils/g504_samples.go create mode 100644 testutils/g505_samples.go create mode 100644 testutils/g601_samples.go create mode 100644 testutils/g602_samples.go create mode 100644 testutils/sample_types.go delete mode 100644 testutils/source.go diff --git a/testutils/cgo_samples.go b/testutils/cgo_samples.go new file mode 100644 index 0000000..e310ddc --- /dev/null +++ b/testutils/cgo_samples.go @@ -0,0 +1,52 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeCgo - Cgo file sample + SampleCodeCgo = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "unsafe" +) + +/* +#include +#include +#include + +int printData(unsigned char *data) { + return printf("cData: %lu \"%s\"\n", (long unsigned int)strlen(data), data); +} +*/ +import "C" + +func main() { + // Allocate C data buffer. + width, height := 8, 2 + lenData := width * height + // add string terminating null byte + cData := (*C.uchar)(C.calloc(C.size_t(lenData+1), C.sizeof_uchar)) + + // When no longer in use, free C allocations. + defer C.free(unsafe.Pointer(cData)) + + // Go slice reference to C data buffer, + // minus string terminating null byte + gData := (*[1 << 30]byte)(unsafe.Pointer(cData))[:lenData:lenData] + + // Write and read cData via gData. + for i := range gData { + gData[i] = '.' + } + copy(gData[0:], "Data") + gData[len(gData)-1] = 'X' + fmt.Printf("gData: %d %q\n", len(gData), gData) + C.printData(cData) +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g101_samples.go b/testutils/g101_samples.go new file mode 100644 index 0000000..dcf7857 --- /dev/null +++ b/testutils/g101_samples.go @@ -0,0 +1,348 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG101 code snippets for hardcoded credentials + SampleCodeG101 = []CodeSample{ + {[]string{` +package main + +import "fmt" + +func main() { + username := "admin" + password := "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" + fmt.Println("Doing something with: ", username, password) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Entropy check should not report this error by default +package main + +import "fmt" + +func main() { + username := "admin" + password := "secret" + fmt.Println("Doing something with: ", username, password) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +var password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" + +func main() { + username := "admin" + fmt.Println("Doing something with: ", username, password) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +const password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" + +func main() { + username := "admin" + fmt.Println("Doing something with: ", username, password) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +const ( + username = "user" + password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" +) + +func main() { + fmt.Println("Doing something with: ", username, password) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +var password string + +func init() { + password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +const ( + ATNStateSomethingElse = 1 + ATNStateTokenStart = 42 +) + +func main() { + println(ATNStateTokenStart) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +const ( + ATNStateTokenStart = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" +) + +func main() { + println(ATNStateTokenStart) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + var password string + if password == "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { + fmt.Println("password equality") + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + var password string + if "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" == password { + fmt.Println("password equality") + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + var password string + if password != "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { + fmt.Println("password equality") + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + var password string + if "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" != password { + fmt.Println("password equality") + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + var p string + if p != "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { + fmt.Println("password equality") + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + var p string + if "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" != p { + fmt.Println("password equality") + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +const ( + pw = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" +) + +func main() { + fmt.Println(pw) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +var ( + pw string +) + +func main() { + pw = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" + fmt.Println(pw) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +const ( + cred = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" +) + +func main() { + fmt.Println(cred) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +var ( + cred string +) + +func main() { + cred = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" + fmt.Println(cred) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +const ( + apiKey = "KjasdlkjapoIKLlka98098sdf012U" +) + +func main() { + fmt.Println(apiKey) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +var ( + apiKey string +) + +func main() { + apiKey = "KjasdlkjapoIKLlka98098sdf012U" + fmt.Println(apiKey) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +const ( + bearer = "Bearer: 2lkjdfoiuwer092834kjdwf09" +) + +func main() { + fmt.Println(bearer) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +var ( + bearer string +) + +func main() { + bearer = "Bearer: 2lkjdfoiuwer092834kjdwf09" + fmt.Println(bearer) +} +`}, 1, gosec.NewConfig()}, + } + + // SampleCodeG101Values code snippets for hardcoded credentials + SampleCodeG101Values = []CodeSample{ + {[]string{` +package main + +import "fmt" + +func main() { + customerNameEnvKey := "FOO_CUSTOMER_NAME" + fmt.Println(customerNameEnvKey) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + txnID := "3637cfcc1eec55a50f78a7c435914583ccbc75a21dec9a0e94dfa077647146d7" + fmt.Println(txnID) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + urlSecret := "https://username:abcdef0123456789abcdef0123456789abcdef01@contoso.com/" + fmt.Println(urlSecret) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + githubToken := "ghp_iR54dhCYg9Tfmoywi9xLmmKZrrnAw438BYh3" + fmt.Println(githubToken) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + awsAccessKeyID := "AKIAI44QH8DHBEXAMPLE" + fmt.Println(awsAccessKeyID) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + compareGoogleAPI := "test" + if compareGoogleAPI == "AIzajtGS_aJGkoiAmSbXzu9I-1eytAi9Lrlh-vT" { + fmt.Println(compareGoogleAPI) + } +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g102_samples.go b/testutils/g102_samples.go new file mode 100644 index 0000000..035808f --- /dev/null +++ b/testutils/g102_samples.go @@ -0,0 +1,106 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG102 code snippets for network binding + SampleCodeG102 = []CodeSample{ + // Bind to all networks explicitly + {[]string{` +package main + +import ( + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", "0.0.0.0:2000") + if err != nil { + log.Fatal(err) + } + defer l.Close() +} +`}, 1, gosec.NewConfig()}, + // Bind to all networks implicitly (default if host omitted) + {[]string{` +package main + +import ( + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":2000") + if err != nil { + log.Fatal(err) + } + defer l.Close() +} +`}, 1, gosec.NewConfig()}, + // Bind to all networks indirectly through a parsing function + {[]string{` +package main + +import ( + "log" + "net" +) + +func parseListenAddr(listenAddr string) (network string, addr string) { + return "", "" +} + +func main() { + addr := ":2000" + l, err := net.Listen(parseListenAddr(addr)) + if err != nil { + log.Fatal(err) + } + defer l.Close() +} +`}, 1, gosec.NewConfig()}, + // Bind to all networks indirectly through a parsing function + {[]string{` +package main + +import ( + "log" + "net" +) + +const addr = ":2000" + +func parseListenAddr(listenAddr string) (network string, addr string) { + return "", "" +} + +func main() { + l, err := net.Listen(parseListenAddr(addr)) + if err != nil { + log.Fatal(err) + } + defer l.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "net" +) + +const addr = "0.0.0.0:2000" + +func main() { + l, err := net.Listen("tcp", addr) + if err != nil { + log.Fatal(err) + } + defer l.Close() +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g103_samples.go b/testutils/g103_samples.go new file mode 100644 index 0000000..ab40a40 --- /dev/null +++ b/testutils/g103_samples.go @@ -0,0 +1,67 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG103 find instances of unsafe blocks for auditing purposes + SampleCodeG103 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "unsafe" +) + +type Fake struct{} + +func (Fake) Good() {} + +func main() { + unsafeM := Fake{} + unsafeM.Good() + intArray := [...]int{1, 2} + fmt.Printf("\nintArray: %v\n", intArray) + intPtr := &intArray[0] + fmt.Printf("\nintPtr=%p, *intPtr=%d.\n", intPtr, *intPtr) + addressHolder := uintptr(unsafe.Pointer(intPtr)) + intPtr = (*int)(unsafe.Pointer(addressHolder)) + fmt.Printf("\nintPtr=%p, *intPtr=%d.\n\n", intPtr, *intPtr) +} +`}, 2, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "unsafe" +) + +func main() { + chars := [...]byte{1, 2} + charsPtr := &chars[0] + str := unsafe.String(charsPtr, len(chars)) + fmt.Printf("%s\n", str) + ptr := unsafe.StringData(str) + fmt.Printf("ptr: %p\n", ptr) +} +`}, 2, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "unsafe" +) + +func main() { + chars := [...]byte{1, 2} + charsPtr := &chars[0] + slice := unsafe.Slice(charsPtr, len(chars)) + fmt.Printf("%v\n", slice) + ptr := unsafe.SliceData(slice) + fmt.Printf("ptr: %p\n", ptr) +} +`}, 2, gosec.NewConfig()}, + } +) diff --git a/testutils/g104_samples.go b/testutils/g104_samples.go new file mode 100644 index 0000000..fcd8ec8 --- /dev/null +++ b/testutils/g104_samples.go @@ -0,0 +1,227 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG104 finds errors that aren't being handled + SampleCodeG104 = []CodeSample{ + {[]string{` +package main + +import "fmt" + +func test() (int,error) { + return 0, nil +} + +func main() { + v, _ := test() + fmt.Println(v) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "io/ioutil" + "os" + "fmt" +) + +func a() error { + return fmt.Errorf("This is an error") +} + +func b() { + fmt.Println("b") + ioutil.WriteFile("foo.txt", []byte("bar"), os.ModeExclusive) +} + +func c() string { + return fmt.Sprintf("This isn't anything") +} + +func main() { + _ = a() + a() + b() + c() +} +`}, 2, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func test() error { + return nil +} + +func main() { + e := test() + fmt.Println(e) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// +build go1.10 + +package main + +import "strings" + +func main() { + var buf strings.Builder + _, err := buf.WriteString("test string") + if err != nil { + panic(err) + } +}`, ` +package main + +func dummy(){} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "bytes" +) + +type a struct { + buf *bytes.Buffer +} + +func main() { + a := &a{ + buf: new(bytes.Buffer), + } + a.buf.Write([]byte{0}) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "io/ioutil" + "os" + "fmt" +) + +func a() { + fmt.Println("a") + ioutil.WriteFile("foo.txt", []byte("bar"), os.ModeExclusive) +} + +func main() { + a() +} +`}, 0, gosec.Config{"G104": map[string]interface{}{"ioutil": []interface{}{"WriteFile"}}}}, + {[]string{` +package main + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" +) + +func createBuffer() *bytes.Buffer { + return new(bytes.Buffer) +} + +func main() { + new(bytes.Buffer).WriteString("*bytes.Buffer") + fmt.Fprintln(os.Stderr, "fmt") + new(strings.Builder).WriteString("*strings.Builder") + _, pw := io.Pipe() + pw.CloseWithError(io.EOF) + + createBuffer().WriteString("*bytes.Buffer") + b := createBuffer() + b.WriteString("*bytes.Buffer") +} +`}, 0, gosec.NewConfig()}, + } // it shouldn't return any errors because all method calls are whitelisted by default + + // SampleCodeG104Audit finds errors that aren't being handled in audit mode + SampleCodeG104Audit = []CodeSample{ + {[]string{` +package main + +import "fmt" + +func test() (int,error) { + return 0, nil +} + +func main() { + v, _ := test() + fmt.Println(v) +} +`}, 1, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, + {[]string{` +package main + +import ( + "io/ioutil" + "os" + "fmt" +) + +func a() error { + return fmt.Errorf("This is an error") +} + +func b() { + fmt.Println("b") + ioutil.WriteFile("foo.txt", []byte("bar"), os.ModeExclusive) +} + +func c() string { + return fmt.Sprintf("This isn't anything") +} + +func main() { + _ = a() + a() + b() + c() +} +`}, 3, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, + {[]string{` +package main + +import "fmt" + +func test() error { + return nil +} + +func main() { + e := test() + fmt.Println(e) +} +`}, 0, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, + {[]string{` +// +build go1.10 + +package main + +import "strings" + +func main() { + var buf strings.Builder + _, err := buf.WriteString("test string") + if err != nil { + panic(err) + } +} +`, ` +package main + +func dummy(){} +`}, 0, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, + } +) diff --git a/testutils/g106_samples.go b/testutils/g106_samples.go new file mode 100644 index 0000000..4845fd1 --- /dev/null +++ b/testutils/g106_samples.go @@ -0,0 +1,20 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG106 - ssh InsecureIgnoreHostKey + SampleCodeG106 = []CodeSample{ + {[]string{` +package main + +import ( + "golang.org/x/crypto/ssh" +) + +func main() { + _ = ssh.InsecureIgnoreHostKey() +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g107_samples.go b/testutils/g107_samples.go new file mode 100644 index 0000000..45ece3e --- /dev/null +++ b/testutils/g107_samples.go @@ -0,0 +1,198 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG107 - SSRF via http requests with variable url + SampleCodeG107 = []CodeSample{ + {[]string{` +// Input from the std in is considered insecure +package main +import ( + "net/http" + "io/ioutil" + "fmt" + "os" + "bufio" +) +func main() { + in := bufio.NewReader(os.Stdin) + url, err := in.ReadString('\n') + if err != nil { + panic(err) + } + resp, err := http.Get(url) + if err != nil { + panic(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + panic(err) + } + fmt.Printf("%s", body) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Variable defined a package level can be changed at any time +// regardless of the initial value +package main + +import ( + "fmt" + "io/ioutil" + "net/http" +) + +var url string = "https://www.google.com" + +func main() { + resp, err := http.Get(url) + if err != nil { + panic(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + panic(err) + } + fmt.Printf("%s", body) +}`}, 1, gosec.NewConfig()}, + {[]string{` +// Environmental variables are not considered as secure source +package main +import ( + "net/http" + "io/ioutil" + "fmt" + "os" +) +func main() { + url := os.Getenv("tainted_url") + resp, err := http.Get(url) + if err != nil { + panic(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + panic(err) + } + fmt.Printf("%s", body) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Constant variables or hard-coded strings are secure +package main + +import ( + "fmt" + "net/http" +) +const url = "http://127.0.0.1" +func main() { + resp, err := http.Get(url) + if err != nil { + fmt.Println(err) + } + fmt.Println(resp.Status) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// A variable at function scope which is initialized to +// a constant string is secure (e.g. cannot be changed concurrently) +package main + +import ( + "fmt" + "net/http" +) +func main() { + var url string = "http://127.0.0.1" + resp, err := http.Get(url) + if err != nil { + fmt.Println(err) + } + fmt.Println(resp.Status) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// A variable at function scope which is initialized to +// a constant string is secure (e.g. cannot be changed concurrently) +package main + +import ( + "fmt" + "net/http" +) +func main() { + url := "http://127.0.0.1" + resp, err := http.Get(url) + if err != nil { + fmt.Println(err) + } + fmt.Println(resp.Status) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// A variable at function scope which is initialized to +// a constant string is secure (e.g. cannot be changed concurrently) +package main + +import ( + "fmt" + "net/http" +) +func main() { + url1 := "test" + var url2 string = "http://127.0.0.1" + url2 = url1 + resp, err := http.Get(url2) + if err != nil { + fmt.Println(err) + } + fmt.Println(resp.Status) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// An exported variable declared a packaged scope is not secure +// because it can changed at any time +package main + +import ( + "fmt" + "net/http" +) + +var Url string + +func main() { + resp, err := http.Get(Url) + if err != nil { + fmt.Println(err) + } + fmt.Println(resp.Status) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// An url provided as a function argument is not secure +package main + +import ( + "fmt" + "net/http" +) +func get(url string) { + resp, err := http.Get(url) + if err != nil { + fmt.Println(err) + } + fmt.Println(resp.Status) +} +func main() { + url := "http://127.0.0.1" + get(url) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g108_samples.go b/testutils/g108_samples.go new file mode 100644 index 0000000..78816ef --- /dev/null +++ b/testutils/g108_samples.go @@ -0,0 +1,42 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG108 - pprof endpoint automatically exposed + SampleCodeG108 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "log" + "net/http" + _ "net/http/pprof" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello World!") + }) + log.Fatal(http.ListenAndServe(":8080", nil)) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "log" + "net/http" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello World!") + }) + log.Fatal(http.ListenAndServe(":8080", nil)) +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g109_samples.go b/testutils/g109_samples.go new file mode 100644 index 0000000..aa50d42 --- /dev/null +++ b/testutils/g109_samples.go @@ -0,0 +1,114 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG109 - Potential Integer OverFlow + SampleCodeG109 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "strconv" +) + +func main() { + bigValue, err := strconv.Atoi("2147483648") + if err != nil { + panic(err) + } + value := int32(bigValue) + fmt.Println(value) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "strconv" +) + +func main() { + bigValue, err := strconv.Atoi("32768") + if err != nil { + panic(err) + } + if int16(bigValue) < 0 { + fmt.Println(bigValue) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "strconv" +) + +func main() { + bigValue, err := strconv.Atoi("2147483648") + if err != nil { + panic(err) + } + fmt.Println(bigValue) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "strconv" +) + +func main() { + bigValue, err := strconv.Atoi("2147483648") + if err != nil { + panic(err) + } + fmt.Println(bigValue) + test() +} + +func test() { + bigValue := 30 + value := int32(bigValue) + fmt.Println(value) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "strconv" +) + +func main() { + value := 10 + if value == 10 { + value, _ := strconv.Atoi("2147483648") + fmt.Println(value) + } + v := int32(value) + fmt.Println(v) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "strconv" +) +func main() { + a, err := strconv.Atoi("a") + b := int32(a) //#nosec G109 + fmt.Println(b, err) +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g110_samples.go b/testutils/g110_samples.go new file mode 100644 index 0000000..397e564 --- /dev/null +++ b/testutils/g110_samples.go @@ -0,0 +1,128 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG110 - potential DoS vulnerability via decompression bomb + SampleCodeG110 = []CodeSample{ + {[]string{` +package main + +import ( + "bytes" + "compress/zlib" + "io" + "os" +) + +func main() { + buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207, + 47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147} + b := bytes.NewReader(buff) + + r, err := zlib.NewReader(b) + if err != nil { + panic(err) + } + _, err = io.Copy(os.Stdout, r) + if err != nil { + panic(err) + } + + r.Close() +}`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "bytes" + "compress/zlib" + "io" + "os" +) + +func main() { + buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207, + 47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147} + b := bytes.NewReader(buff) + + r, err := zlib.NewReader(b) + if err != nil { + panic(err) + } + buf := make([]byte, 8) + _, err = io.CopyBuffer(os.Stdout, r, buf) + if err != nil { + panic(err) + } + r.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "archive/zip" + "io" + "os" + "strconv" +) + +func main() { + r, err := zip.OpenReader("tmp.zip") + if err != nil { + panic(err) + } + defer r.Close() + + for i, f := range r.File { + out, err := os.OpenFile("output" + strconv.Itoa(i), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + if err != nil { + panic(err) + } + + rc, err := f.Open() + if err != nil { + panic(err) + } + + _, err = io.Copy(out, rc) + + out.Close() + rc.Close() + + if err != nil { + panic(err) + } + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "io" + "os" +) + +func main() { + s, err := os.Open("src") + if err != nil { + panic(err) + } + defer s.Close() + + d, err := os.Create("dst") + if err != nil { + panic(err) + } + defer d.Close() + + _, err = io.Copy(d, s) + if err != nil { + panic(err) + } +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g111_samples.go b/testutils/g111_samples.go new file mode 100644 index 0000000..e888f03 --- /dev/null +++ b/testutils/g111_samples.go @@ -0,0 +1,29 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG111 - potential directory traversal + SampleCodeG111 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "log" + "net/http" + "os" +) + +func main() { + http.Handle("/bad/", http.StripPrefix("/bad/", http.FileServer(http.Dir("/")))) + http.HandleFunc("/", HelloServer) + log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil)) +} + +func HelloServer(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g112_samples.go b/testutils/g112_samples.go new file mode 100644 index 0000000..c356c81 --- /dev/null +++ b/testutils/g112_samples.go @@ -0,0 +1,107 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG112 - potential slowloris attack + SampleCodeG112 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "net/http" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) + }) + err := (&http.Server{ + Addr: ":1234", + }).ListenAndServe() + if err != nil { + panic(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "time" + "net/http" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) + }) + server := &http.Server{ + Addr: ":1234", + ReadHeaderTimeout: 3 * time.Second, + } + err := server.ListenAndServe() + if err != nil { + panic(err) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "time" + "net/http" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) + }) + server := &http.Server{ + Addr: ":1234", + ReadTimeout: 1 * time.Second, + } + err := server.ListenAndServe() + if err != nil { + panic(err) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "net/http" + "sync" +) + +type Server struct { + hs *http.Server + mux *http.ServeMux + mu sync.Mutex +} + +func New(listenAddr string) *Server { + mux := http.NewServeMux() + + return &Server{ + hs: &http.Server{ // #nosec G112 - Not publicly exposed + Addr: listenAddr, + Handler: mux, + }, + mux: mux, + mu: sync.Mutex{}, + } +} + +func main() { + fmt.Print("test") +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g113_samples.go b/testutils/g113_samples.go new file mode 100644 index 0000000..16b613f --- /dev/null +++ b/testutils/g113_samples.go @@ -0,0 +1,24 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG113 - Usage of Rat.SetString in math/big with an overflow + SampleCodeG113 = []CodeSample{ + {[]string{` +package main + +import ( + "math/big" + "fmt" +) + +func main() { + r := big.Rat{} + r.SetString("13e-9223372036854775808") + + fmt.Println(r) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g114_samples.go b/testutils/g114_samples.go new file mode 100644 index 0000000..44cdcde --- /dev/null +++ b/testutils/g114_samples.go @@ -0,0 +1,73 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG114 - Use of net/http serve functions that have no support for setting timeouts + SampleCodeG114 = []CodeSample{ + {[]string{` +package main + +import ( + "log" + "net/http" +) + +func main() { + err := http.ListenAndServe(":8080", nil) + log.Fatal(err) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "net/http" +) + +func main() { + err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil) + log.Fatal(err) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "net" + "net/http" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatal(err) + } + defer l.Close() + err = http.Serve(l, nil) + log.Fatal(err) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "net" + "net/http" +) + +func main() { + l, err := net.Listen("tcp", ":8443") + if err != nil { + log.Fatal(err) + } + defer l.Close() + err = http.ServeTLS(l, nil, "cert.pem", "key.pem") + log.Fatal(err) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g201_samples.go b/testutils/g201_samples.go new file mode 100644 index 0000000..94ad7c0 --- /dev/null +++ b/testutils/g201_samples.go @@ -0,0 +1,403 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG201 - SQL injection via format string + SampleCodeG201 = []CodeSample{ + {[]string{` +// Format string without proper quoting +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT * FROM foo where name = '%s'", os.Args[1]) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Format string without proper quoting case insensitive +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("select * from foo where name = '%s'", os.Args[1]) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Format string without proper quoting with context +package main +import ( + "context" + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("select * from foo where name = '%s'", os.Args[1]) + rows, err := db.QueryContext(context.Background(), q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Format string without proper quoting with transaction +package main +import ( + "context" + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + tx, err := db.Begin() + if err != nil { + panic(err) + } + defer tx.Rollback() + q := fmt.Sprintf("select * from foo where name = '%s'", os.Args[1]) + rows, err := tx.QueryContext(context.Background(), q) + if err != nil { + panic(err) + } + defer rows.Close() + if err := tx.Commit(); err != nil { + panic(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Format string false positive, safe string spec. +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT * FROM foo where id = %d", os.Args[1]) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Format string false positive +package main + +import ( + "database/sql" +) + +const staticQuery = "SELECT * FROM foo WHERE age < 32" + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query(staticQuery) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Format string false positive, quoted formatter argument. +package main + +import ( + "database/sql" + "fmt" + "os" + "github.com/lib/pq" +) + +func main(){ + db, err := sql.Open("postgres", "localhost") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT * FROM %s where id = 1", pq.QuoteIdentifier(os.Args[1])) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// false positive +package main + +import ( + "database/sql" + "fmt" +) + +const Table = "foo" +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT * FROM %s where id = 1", Table) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main +import ( + "fmt" +) + +func main(){ + fmt.Sprintln() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Format string with \n\r +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT * FROM foo where\n name = '%s'", os.Args[1]) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Format string with \n\r +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT * FROM foo where\nname = '%s'", os.Args[1]) + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// SQLI by db.Query(some).Scan(&other) +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main() { + var name string + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT name FROM users where id = '%s'", os.Args[1]) + row := db.QueryRow(q) + err = row.Scan(&name) + if err != nil { + panic(err) + } + defer db.Close() +}`}, 1, gosec.NewConfig()}, + {[]string{` +// SQLI by db.Query(some).Scan(&other) +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main() { + var name string + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT name FROM users where id = '%s'", os.Args[1]) + err = db.QueryRow(q).Scan(&name) + if err != nil { + panic(err) + } + defer db.Close() +}`}, 1, gosec.NewConfig()}, + {[]string{` +// SQLI by db.Prepare(some) +package main + +import ( + "database/sql" + "fmt" + "log" + "os" +) + +const Table = "foo" + +func main() { + var album string + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT name FROM users where '%s' = ?", os.Args[1]) + stmt, err := db.Prepare(q) + if err != nil { + log.Fatal(err) + } + stmt.QueryRow(fmt.Sprintf("%s", os.Args[2])).Scan(&album) + if err != nil { + if err == sql.ErrNoRows { + log.Fatal(err) + } + } + defer stmt.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// SQLI by db.PrepareContext(some) +package main + +import ( + "context" + "database/sql" + "fmt" + "log" + "os" +) + +const Table = "foo" + +func main() { + var album string + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + q := fmt.Sprintf("SELECT name FROM users where '%s' = ?", os.Args[1]) + stmt, err := db.PrepareContext(context.Background(), q) + if err != nil { + log.Fatal(err) + } + stmt.QueryRow(fmt.Sprintf("%s", os.Args[2])).Scan(&album) + if err != nil { + if err == sql.ErrNoRows { + log.Fatal(err) + } + } + defer stmt.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// false positive +package main + +import ( + "database/sql" + "fmt" + "log" + "os" +) + +const Table = "foo" + +func main() { + var album string + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + stmt, err := db.Prepare("SELECT * FROM album WHERE id = ?") + if err != nil { + log.Fatal(err) + } + stmt.QueryRow(fmt.Sprintf("%s", os.Args[1])).Scan(&album) + if err != nil { + if err == sql.ErrNoRows { + log.Fatal(err) + } + } + defer stmt.Close() +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g202_samples.go b/testutils/g202_samples.go new file mode 100644 index 0000000..c5f55d7 --- /dev/null +++ b/testutils/g202_samples.go @@ -0,0 +1,284 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG202 - SQL query string building via string concatenation + SampleCodeG202 = []CodeSample{ + {[]string{` +// infixed concatenation +package main + +import ( + "database/sql" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + + q := "INSERT INTO foo (name) VALUES ('" + os.Args[0] + "')" + rows, err := db.Query(q) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "database/sql" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query("SELECT * FROM foo WHERE name = " + os.Args[1]) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// case insensitive match +package main + +import ( + "database/sql" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query("select * from foo where name = " + os.Args[1]) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// context match +package main + +import ( + "context" + "database/sql" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.QueryContext(context.Background(), "select * from foo where name = " + os.Args[1]) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// DB transaction check +package main + +import ( + "context" + "database/sql" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + tx, err := db.Begin() + if err != nil { + panic(err) + } + defer tx.Rollback() + rows, err := tx.QueryContext(context.Background(), "select * from foo where name = " + os.Args[1]) + if err != nil { + panic(err) + } + defer rows.Close() + if err := tx.Commit(); err != nil { + panic(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// multiple string concatenation +package main + +import ( + "database/sql" + "os" +) + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query("SELECT * FROM foo" + "WHERE name = " + os.Args[1]) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// false positive +package main + +import ( + "database/sql" +) + +var staticQuery = "SELECT * FROM foo WHERE age < " +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query(staticQuery + "32") + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "database/sql" +) + +const age = "32" + +var staticQuery = "SELECT * FROM foo WHERE age < " + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query(staticQuery + age) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +const gender = "M" +`, ` +package main + +import ( + "database/sql" +) + +const age = "32" + +var staticQuery = "SELECT * FROM foo WHERE age < " + +func main(){ + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + rows, err := db.Query("SELECT * FROM foo WHERE gender = " + gender) + if err != nil { + panic(err) + } + defer rows.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// ExecContext match +package main + +import ( + "context" + "database/sql" + "fmt" + "os" +) + +func main() { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + result, err := db.ExecContext(context.Background(), "select * from foo where name = "+os.Args[1]) + if err != nil { + panic(err) + } + fmt.Println(result) +}`}, 1, gosec.NewConfig()}, + {[]string{` +// Exec match +package main + +import ( + "database/sql" + "fmt" + "os" +) + +func main() { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + result, err := db.Exec("select * from foo where name = " + os.Args[1]) + if err != nil { + panic(err) + } + fmt.Println(result) +}`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "database/sql" + "fmt" +) +const gender = "M" +const age = "32" + +var staticQuery = "SELECT * FROM foo WHERE age < " + +func main() { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + panic(err) + } + result, err := db.Exec("SELECT * FROM foo WHERE gender = " + gender) + if err != nil { + panic(err) + } + fmt.Println(result) +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g203_samples.go b/testutils/g203_samples.go new file mode 100644 index 0000000..9e689eb --- /dev/null +++ b/testutils/g203_samples.go @@ -0,0 +1,92 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG203 - Template checks + SampleCodeG203 = []CodeSample{ + {[]string{` +// We assume that hardcoded template strings are safe as the programmer would +// need to be explicitly shooting themselves in the foot (as below) +package main + +import ( + "html/template" + "os" +) + +const tmpl = "" + +func main() { + t := template.Must(template.New("ex").Parse(tmpl)) + v := map[string]interface{}{ + "Title": "Test World", + "Body": template.HTML(""), + } + t.Execute(os.Stdout, v) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Using a variable to initialize could potentially be dangerous. Under the +// current model this will likely produce some false positives. +package main + +import ( + "html/template" + "os" +) + +const tmpl = "" + +func main() { + a := "something from another place" + t := template.Must(template.New("ex").Parse(tmpl)) + v := map[string]interface{}{ + "Title": "Test World", + "Body": template.HTML(a), + } + t.Execute(os.Stdout, v) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "html/template" + "os" +) + +const tmpl = "" + +func main() { + a := "something from another place" + t := template.Must(template.New("ex").Parse(tmpl)) + v := map[string]interface{}{ + "Title": "Test World", + "Body": template.JS(a), + } + t.Execute(os.Stdout, v) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "html/template" + "os" +) + +const tmpl = "" + +func main() { + a := "something from another place" + t := template.Must(template.New("ex").Parse(tmpl)) + v := map[string]interface{}{ + "Title": "Test World", + "Body": template.URL(a), + } + t.Execute(os.Stdout, v) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g204_samples.go b/testutils/g204_samples.go new file mode 100644 index 0000000..a7fb693 --- /dev/null +++ b/testutils/g204_samples.go @@ -0,0 +1,246 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG204 - Subprocess auditing + SampleCodeG204 = []CodeSample{ + {[]string{` +package main + +import ( + "log" + "os/exec" + "context" +) + +func main() { + err := exec.CommandContext(context.Background(), "git", "rev-parse", "--show-toplevel").Run() + if err != nil { + log.Fatal(err) + } + log.Printf("Command finished with error: %v", err) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Calling any function which starts a new process with using +// command line arguments as it's arguments is considered dangerous +package main + +import ( + "context" + "log" + "os" + "os/exec" +) + +func main() { + err := exec.CommandContext(context.Background(), os.Args[0], "5").Run() + if err != nil { + log.Fatal(err) + } + log.Printf("Command finished with error: %v", err) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Initializing a local variable using a environmental +// variable is consider as a dangerous user input +package main + +import ( + "log" + "os" + "os/exec" +) + +func main() { + run := "sleep" + os.Getenv("SOMETHING") + cmd := exec.Command(run, "5") + err := cmd.Start() + if err != nil { + log.Fatal(err) + } + log.Printf("Waiting for command to finish...") + err = cmd.Wait() + log.Printf("Command finished with error: %v", err) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// gosec doesn't have enough context to decide that the +// command argument of the RunCmd function is hardcoded string +// and that's why it's better to warn the user so he can audit it +package main + +import ( + "log" + "os/exec" +) + +func RunCmd(command string) { + cmd := exec.Command(command, "5") + err := cmd.Start() + if err != nil { + log.Fatal(err) + } + log.Printf("Waiting for command to finish...") + err = cmd.Wait() +} + +func main() { + RunCmd("sleep") +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "os/exec" +) + +func RunCmd(a string, c string) { + cmd := exec.Command(c) + err := cmd.Start() + if err != nil { + log.Fatal(err) + } + log.Printf("Waiting for command to finish...") + err = cmd.Wait() + + cmd = exec.Command(a) + err = cmd.Start() + if err != nil { + log.Fatal(err) + } + log.Printf("Waiting for command to finish...") + err = cmd.Wait() +} + +func main() { + RunCmd("ll", "ls") +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// syscall.Exec function called with hardcoded arguments +// shouldn't be consider as a command injection +package main + +import ( + "fmt" + "syscall" +) + +func main() { + err := syscall.Exec("/bin/cat", []string{"/etc/passwd"}, nil) + if err != nil { + fmt.Printf("Error: %v\n", err) + } +} +`}, 0, gosec.NewConfig()}, + { + []string{` +package main + +import ( + "fmt" + "syscall" +) + +func RunCmd(command string) { + _, err := syscall.ForkExec(command, []string{}, nil) + if err != nil { + fmt.Printf("Error: %v\n", err) + } +} + +func main() { + RunCmd("sleep") +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "syscall" +) + +func RunCmd(command string) { + _, _, err := syscall.StartProcess(command, []string{}, nil) + if err != nil { + fmt.Printf("Error: %v\n", err) + } +} + +func main() { + RunCmd("sleep") +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// starting a process with a variable as an argument +// even if not constant is not considered as dangerous +// because it has hardcoded value +package main + +import ( + "log" + "os/exec" +) + +func main() { + run := "sleep" + cmd := exec.Command(run, "5") + err := cmd.Start() + if err != nil { + log.Fatal(err) + } + log.Printf("Waiting for command to finish...") + err = cmd.Wait() + log.Printf("Command finished with error: %v", err) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// exec.Command from supplemental package sys/execabs +// using variable arguments +package main + +import ( + "context" + "log" + "os" + exec "golang.org/x/sys/execabs" +) + +func main() { + err := exec.CommandContext(context.Background(), os.Args[0], "5").Run() + if err != nil { + log.Fatal(err) + } + log.Printf("Command finished with error: %v", err) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Initializing a local variable using a environmental +// variable is consider as a dangerous user input +package main + +import ( + "log" + "os" + "os/exec" +) + +func main() { + var run = "sleep" + os.Getenv("SOMETHING") + cmd := exec.Command(run, "5") + err := cmd.Start() + if err != nil { + log.Fatal(err) + } + log.Printf("Waiting for command to finish...") + err = cmd.Wait() + log.Printf("Command finished with error: %v", err) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g301_samples.go b/testutils/g301_samples.go new file mode 100644 index 0000000..9bce70a --- /dev/null +++ b/testutils/g301_samples.go @@ -0,0 +1,56 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( // SampleCodeG301 - mkdir permission check + SampleCodeG301 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + err := os.Mkdir("/tmp/mydir", 0777) + if err != nil { + fmt.Println("Error when creating a directory!") + return + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + err := os.MkdirAll("/tmp/mydir", 0777) + if err != nil { + fmt.Println("Error when creating a directory!") + return + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + err := os.Mkdir("/tmp/mydir", 0600) + if err != nil { + fmt.Println("Error when creating a directory!") + return + } +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g302_samples.go b/testutils/g302_samples.go new file mode 100644 index 0000000..4bef26b --- /dev/null +++ b/testutils/g302_samples.go @@ -0,0 +1,73 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG302 - file create / chmod permissions check + SampleCodeG302 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + err := os.Chmod("/tmp/somefile", 0777) + if err != nil { + fmt.Println("Error when changing file permissions!") + return + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + _, err := os.OpenFile("/tmp/thing", os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + fmt.Println("Error opening a file!") + return + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + err := os.Chmod("/tmp/mydir", 0400) + if err != nil { + fmt.Println("Error") + return + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func main() { + _, err := os.OpenFile("/tmp/thing", os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + fmt.Println("Error opening a file!") + return + } +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g303_samples.go b/testutils/g303_samples.go new file mode 100644 index 0000000..3c941b9 --- /dev/null +++ b/testutils/g303_samples.go @@ -0,0 +1,61 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG303 - bad tempfile permissions & hardcoded shared path + SampleCodeG303 = []CodeSample{ + {[]string{` +package samples + +import ( + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" +) + +func main() { + err := ioutil.WriteFile("/tmp/demo2", []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + f, err := os.Create("/tmp/demo2") + if err != nil { + fmt.Println("Error while writing!") + } else if err = f.Close(); err != nil { + fmt.Println("Error while closing!") + } + err = os.WriteFile("/tmp/demo2", []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + err = os.WriteFile("/usr/tmp/demo2", []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + err = os.WriteFile("/tmp/" + "demo2", []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + err = os.WriteFile(os.TempDir() + "/demo2", []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + err = os.WriteFile(path.Join("/var/tmp", "demo2"), []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + err = os.WriteFile(path.Join(os.TempDir(), "demo2"), []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } + err = os.WriteFile(filepath.Join(os.TempDir(), "demo2"), []byte("This is some data"), 0644) + if err != nil { + fmt.Println("Error while writing!") + } +} +`}, 9, gosec.NewConfig()}, + } +) diff --git a/testutils/g304_samples.go b/testutils/g304_samples.go new file mode 100644 index 0000000..33de51c --- /dev/null +++ b/testutils/g304_samples.go @@ -0,0 +1,307 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG304 - potential file inclusion vulnerability + SampleCodeG304 = []CodeSample{ + {[]string{` +package main + +import ( +"os" +"io/ioutil" +"log" +) + +func main() { + f := os.Getenv("tainted_file") + body, err := ioutil.ReadFile(f) + if err != nil { + log.Printf("Error: %v\n", err) + } + log.Print(body) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( +"os" +"log" +) + +func main() { + f := os.Getenv("tainted_file") + body, err := os.ReadFile(f) + if err != nil { + log.Printf("Error: %v\n", err) + } + log.Print(body) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "log" + "net/http" + "os" +) + +func main() { + http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { + title := r.URL.Query().Get("title") + f, err := os.Open(title) + if err != nil { + fmt.Printf("Error: %v\n", err) + } + body := make([]byte, 5) + if _, err = f.Read(body); err != nil { + fmt.Printf("Error: %v\n", err) + } + fmt.Fprintf(w, "%s", body) + }) + log.Fatal(http.ListenAndServe(":3000", nil)) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "log" + "net/http" + "os" +) + +func main() { + http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { + title := r.URL.Query().Get("title") + f, err := os.OpenFile(title, os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + fmt.Printf("Error: %v\n", err) + } + body := make([]byte, 5) + if _, err = f.Read(body); err != nil { + fmt.Printf("Error: %v\n", err) + } + fmt.Fprintf(w, "%s", body) + }) + log.Fatal(http.ListenAndServe(":3000", nil)) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "os" + "io/ioutil" +) + + func main() { + f2 := os.Getenv("tainted_file2") + body, err := ioutil.ReadFile("/tmp/" + f2) + if err != nil { + log.Printf("Error: %v\n", err) + } + log.Print(body) + } + `}, 1, gosec.NewConfig()}, + {[]string{` + package main + + import ( + "bufio" + "fmt" + "os" + "path/filepath" + ) + +func main() { + reader := bufio.NewReader(os.Stdin) + fmt.Print("Please enter file to read: ") + file, _ := reader.ReadString('\n') + file = file[:len(file)-1] + f, err := os.Open(filepath.Join("/tmp/service/", file)) + if err != nil { + fmt.Printf("Error: %v\n", err) + } + contents := make([]byte, 15) + if _, err = f.Read(contents); err != nil { + fmt.Printf("Error: %v\n", err) + } + fmt.Println(string(contents)) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "log" + "os" + "io/ioutil" + "path/filepath" +) + +func main() { + dir := os.Getenv("server_root") + f3 := os.Getenv("tainted_file3") + // edge case where both a binary expression and file Join are used. + body, err := ioutil.ReadFile(filepath.Join("/var/"+dir, f3)) + if err != nil { + log.Printf("Error: %v\n", err) + } + log.Print(body) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "os" + "path/filepath" +) + +func main() { + repoFile := "path_of_file" + cleanRepoFile := filepath.Clean(repoFile) + _, err := os.OpenFile(cleanRepoFile, os.O_RDONLY, 0600) + if err != nil { + panic(err) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "os" + "path/filepath" +) + +func openFile(filePath string) { + _, err := os.OpenFile(filepath.Clean(filePath), os.O_RDONLY, 0600) + if err != nil { + panic(err) + } +} + +func main() { + repoFile := "path_of_file" + openFile(repoFile) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "os" + "path/filepath" +) + +func openFile(dir string, filePath string) { + fp := filepath.Join(dir, filePath) + fp = filepath.Clean(fp) + _, err := os.OpenFile(fp, os.O_RDONLY, 0600) + if err != nil { + panic(err) + } +} + +func main() { + repoFile := "path_of_file" + dir := "path_of_dir" + openFile(dir, repoFile) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "os" + "path/filepath" +) + +func main() { + repoFile := "path_of_file" + relFile, err := filepath.Rel("./", repoFile) + if err != nil { + panic(err) + } + _, err = os.OpenFile(relFile, os.O_RDONLY, 0600) + if err != nil { + panic(err) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "io" + "os" +) + +func createFile(file string) *os.File { + f, err := os.Create(file) + if err != nil { + panic(err) + } + return f +} + +func main() { + s, err := os.Open("src") + if err != nil { + panic(err) + } + defer s.Close() + + d := createFile("dst") + defer d.Close() + + _, err = io.Copy(d, s) + if err != nil { + panic(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "path/filepath" +) + +type foo struct { +} + +func (f *foo) doSomething(silly string) error { + whoCares, err := filepath.Rel(THEWD, silly) + if err != nil { + return err + } + fmt.Printf("%s", whoCares) + return nil +} + +func main() { + f := &foo{} + + if err := f.doSomething("irrelevant"); err != nil { + panic(err) + } +} +`, ` +package main + +var THEWD string +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g305_samples.go b/testutils/g305_samples.go new file mode 100644 index 0000000..cb98706 --- /dev/null +++ b/testutils/g305_samples.go @@ -0,0 +1,178 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG305 - File path traversal when extracting zip/tar archives + SampleCodeG305 = []CodeSample{ + {[]string{` +package unzip + +import ( + "archive/zip" + "io" + "os" + "path/filepath" +) + +func unzip(archive, target string) error { + reader, err := zip.OpenReader(archive) + if err != nil { + return err + } + + if err := os.MkdirAll(target, 0750); err != nil { + return err + } + + for _, file := range reader.File { + path := filepath.Join(target, file.Name) + if file.FileInfo().IsDir() { + os.MkdirAll(path, file.Mode()) //#nosec + continue + } + + fileReader, err := file.Open() + if err != nil { + return err + } + defer fileReader.Close() + + targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) + if err != nil { + return err + } + defer targetFile.Close() + + if _, err := io.Copy(targetFile, fileReader); err != nil { + return err + } + } + + return nil +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package unzip + +import ( + "archive/zip" + "io" + "os" + "path/filepath" +) + +func unzip(archive, target string) error { + reader, err := zip.OpenReader(archive) + if err != nil { + return err + } + + if err := os.MkdirAll(target, 0750); err != nil { + return err + } + + for _, file := range reader.File { + archiveFile := file.Name + path := filepath.Join(target, archiveFile) + if file.FileInfo().IsDir() { + os.MkdirAll(path, file.Mode()) //#nosec + continue + } + + fileReader, err := file.Open() + if err != nil { + return err + } + defer fileReader.Close() + + targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) + if err != nil { + return err + } + defer targetFile.Close() + + if _, err := io.Copy(targetFile, fileReader); err != nil { + return err + } + } + + return nil +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package zip + +import ( + "archive/zip" + "io" + "os" + "path" +) + +func extractFile(f *zip.File, destPath string) error { + filePath := path.Join(destPath, f.Name) + os.MkdirAll(path.Dir(filePath), os.ModePerm) + + rc, err := f.Open() + if err != nil { + return err + } + defer rc.Close() + + fw, err := os.Create(filePath) + if err != nil { + return err + } + defer fw.Close() + + if _, err = io.Copy(fw, rc); err != nil { + return err + } + + if f.FileInfo().Mode()&os.ModeSymlink != 0 { + return nil + } + + if err = os.Chtimes(filePath, f.ModTime(), f.ModTime()); err != nil { + return err + } + return os.Chmod(filePath, f.FileInfo().Mode()) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package tz + +import ( + "archive/tar" + "io" + "os" + "path" +) + +func extractFile(f *tar.Header, tr *tar.Reader, destPath string) error { + filePath := path.Join(destPath, f.Name) + os.MkdirAll(path.Dir(filePath), os.ModePerm) + + fw, err := os.Create(filePath) + if err != nil { + return err + } + defer fw.Close() + + if _, err = io.Copy(fw, tr); err != nil { + return err + } + + if f.FileInfo().Mode()&os.ModeSymlink != 0 { + return nil + } + + if err = os.Chtimes(filePath, f.FileInfo().ModTime(), f.FileInfo().ModTime()); err != nil { + return err + } + return os.Chmod(filePath, f.FileInfo().Mode()) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g306_samples.go b/testutils/g306_samples.go new file mode 100644 index 0000000..d1cb34c --- /dev/null +++ b/testutils/g306_samples.go @@ -0,0 +1,58 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG306 - Poor permissions for WriteFile + SampleCodeG306 = []CodeSample{ + {[]string{` +package main + +import ( + "bufio" + "fmt" + "io/ioutil" + "os" +) + +func check(e error) { + if e != nil { + panic(e) + } +} + +func main() { + + d1 := []byte("hello\ngo\n") + err := ioutil.WriteFile("/tmp/dat1", d1, 0744) + check(err) + + allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600) + check(allowed) + + f, err := os.Create("/tmp/dat2") + check(err) + + defer f.Close() + + d2 := []byte{115, 111, 109, 101, 10} + n2, err := f.Write(d2) + + defer check(err) + fmt.Printf("wrote %d bytes\n", n2) + + n3, err := f.WriteString("writes\n") + fmt.Printf("wrote %d bytes\n", n3) + + f.Sync() + + w := bufio.NewWriter(f) + n4, err := w.WriteString("buffered\n") + fmt.Printf("wrote %d bytes\n", n4) + + w.Flush() + +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g307_samples.go b/testutils/g307_samples.go new file mode 100644 index 0000000..1f7cf6d --- /dev/null +++ b/testutils/g307_samples.go @@ -0,0 +1,49 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG307 - Poor permissions for os.Create + SampleCodeG307 = []CodeSample{ + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func check(e error) { + if e != nil { + panic(e) + } +} + +func main() { + f, err := os.Create("/tmp/dat2") + check(err) + defer f.Close() +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" + "os" +) + +func check(e error) { + if e != nil { + panic(e) + } +} + +func main() { + f, err := os.Create("/tmp/dat2") + check(err) + defer f.Close() +} +`}, 1, gosec.Config{"G307": "0o600"}}, + } +) diff --git a/testutils/g401_samples.go b/testutils/g401_samples.go new file mode 100644 index 0000000..86bf23b --- /dev/null +++ b/testutils/g401_samples.go @@ -0,0 +1,69 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG401 - Use of weak crypto MD5 + SampleCodeG401 = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/md5" + "fmt" + "io" + "log" + "os" +) + +func main() { + f, err := os.Open("file.txt") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + defer func() { + err := f.Close() + if err != nil { + log.Printf("error closing the file: %s", err) + } + }() + + h := md5.New() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + fmt.Printf("%x", h.Sum(nil)) +} +`}, 1, gosec.NewConfig()}, + } + + // SampleCodeG401b - Use of weak crypto SHA1 + SampleCodeG401b = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/sha1" + "fmt" + "io" + "log" + "os" +) +func main() { + f, err := os.Open("file.txt") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + h := sha1.New() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + fmt.Printf("%x", h.Sum(nil)) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g402_samples.go b/testutils/g402_samples.go new file mode 100644 index 0000000..999b4c2 --- /dev/null +++ b/testutils/g402_samples.go @@ -0,0 +1,298 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG402 - TLS settings + SampleCodeG402 = []CodeSample{ + {[]string{` +// InsecureSkipVerify +package main + +import ( + "crypto/tls" + "fmt" + "net/http" +) + +func main() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + + client := &http.Client{Transport: tr} + _, err := client.Get("https://golang.org/") + if err != nil { + fmt.Println(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// InsecureSkipVerify from variable +package main + +import ( + "crypto/tls" +) + +func main() { + var conf tls.Config + conf.InsecureSkipVerify = true +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Insecure minimum version +package main + +import ( + "crypto/tls" + "fmt" + "net/http" +) + +func main() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{MinVersion: 0}, + } + client := &http.Client{Transport: tr} + _, err := client.Get("https://golang.org/") + if err != nil { + fmt.Println(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Insecure minimum version +package main + +import ( + "crypto/tls" + "fmt" +) + +func CaseNotError() *tls.Config { + var v uint16 = tls.VersionTLS13 + + return &tls.Config{ + MinVersion: v, + } +} + +func main() { + a := CaseNotError() + fmt.Printf("Debug: %v\n", a.MinVersion) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Insecure minimum version +package main + +import ( + "crypto/tls" + "fmt" +) + +func CaseNotError() *tls.Config { + return &tls.Config{ + MinVersion: tls.VersionTLS13, + } +} + +func main() { + a := CaseNotError() + fmt.Printf("Debug: %v\n", a.MinVersion) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Insecure minimum version +package main +import ( + "crypto/tls" + "fmt" +) + +func CaseError() *tls.Config { + var v = &tls.Config{ + MinVersion: 0, + } + return v +} + +func main() { + a := CaseError() + fmt.Printf("Debug: %v\n", a.MinVersion) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Insecure minimum version +package main + +import ( + "crypto/tls" + "fmt" +) + +func CaseError() *tls.Config { + var v = &tls.Config{ + MinVersion: getVersion(), + } + return v +} + +func getVersion() uint16 { + return tls.VersionTLS12 +} + +func main() { + a := CaseError() + fmt.Printf("Debug: %v\n", a.MinVersion) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Insecure minimum version +package main + +import ( + "crypto/tls" + "fmt" + "net/http" +) + +var theValue uint16 = 0x0304 + +func main() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{MinVersion: theValue}, + } + client := &http.Client{Transport: tr} + _, err := client.Get("https://golang.org/") + if err != nil { + fmt.Println(err) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +// Insecure max version +package main + +import ( + "crypto/tls" + "fmt" + "net/http" +) + +func main() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{MaxVersion: 0}, + } + client := &http.Client{Transport: tr} + _, err := client.Get("https://golang.org/") + if err != nil { + fmt.Println(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// Insecure ciphersuite selection +package main + +import ( + "crypto/tls" + "fmt" + "net/http" +) + +func main() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + } + client := &http.Client{Transport: tr} + _, err := client.Get("https://golang.org/") + if err != nil { + fmt.Println(err) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// secure max version when min version is specified +package main + +import ( + "crypto/tls" + "fmt" + "net/http" +) + +func main() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + MaxVersion: 0, + MinVersion: tls.VersionTLS13, + }, + } + client := &http.Client{Transport: tr} + _, err := client.Get("https://golang.org/") + if err != nil { + fmt.Println(err) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package p0 + +import "crypto/tls" + +func TlsConfig0() *tls.Config { + var v uint16 = 0 + return &tls.Config{MinVersion: v} +} +`, ` +package p0 + +import "crypto/tls" + +func TlsConfig1() *tls.Config { + return &tls.Config{MinVersion: 0x0304} +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "crypto/tls" + "fmt" +) + +func main() { + cfg := tls.Config{ + MinVersion: MinVer, + } + fmt.Println("tls min version", cfg.MinVersion) +} +`, ` +package main + +import "crypto/tls" + +const MinVer = tls.VersionTLS13 +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "crypto/tls" + cryptotls "crypto/tls" +) + +func main() { + _ = tls.Config{MinVersion: tls.VersionTLS12} + _ = cryptotls.Config{MinVersion: cryptotls.VersionTLS12} +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/g403_samples.go b/testutils/g403_samples.go new file mode 100644 index 0000000..2618534 --- /dev/null +++ b/testutils/g403_samples.go @@ -0,0 +1,27 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG403 - weak key strength + SampleCodeG403 = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/rand" + "crypto/rsa" + "fmt" +) + +func main() { + //Generate Private Key + pvk, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + fmt.Println(err) + } + fmt.Println(pvk) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g404_samples.go b/testutils/g404_samples.go new file mode 100644 index 0000000..95266c3 --- /dev/null +++ b/testutils/g404_samples.go @@ -0,0 +1,104 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG404 - weak random number + SampleCodeG404 = []CodeSample{ + {[]string{` +package main + +import "crypto/rand" + +func main() { + good, _ := rand.Read(nil) + println(good) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "math/rand" + +func main() { + bad := rand.Int() + println(bad) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "crypto/rand" + mrand "math/rand" +) + +func main() { + good, _ := rand.Read(nil) + println(good) + bad := mrand.Int31() + println(bad) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "math/rand" +) + +func main() { + gen := rand.New(rand.NewSource(10)) + bad := gen.Int() + println(bad) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "math/rand" +) + +func main() { + bad := rand.Intn(10) + println(bad) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "crypto/rand" + "math/big" + rnd "math/rand" +) + +func main() { + good, _ := rand.Int(rand.Reader, big.NewInt(int64(2))) + println(good) + bad := rnd.Intn(2) + println(bad) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + crand "crypto/rand" + "math/big" + "math/rand" + rand2 "math/rand" + rand3 "math/rand" +) + +func main() { + _, _ = crand.Int(crand.Reader, big.NewInt(int64(2))) // good + + _ = rand.Intn(2) // bad + _ = rand2.Intn(2) // bad + _ = rand3.Intn(2) // bad +} +`}, 3, gosec.NewConfig()}, + } +) diff --git a/testutils/g501_samples.go b/testutils/g501_samples.go new file mode 100644 index 0000000..ca7aa74 --- /dev/null +++ b/testutils/g501_samples.go @@ -0,0 +1,24 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG501 - Blocklisted import MD5 + SampleCodeG501 = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/md5" + "fmt" + "os" +) + +func main() { + for _, arg := range os.Args { + fmt.Printf("%x - %s\n", md5.Sum([]byte(arg)), arg) + } +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g502_samples.go b/testutils/g502_samples.go new file mode 100644 index 0000000..fa92e58 --- /dev/null +++ b/testutils/g502_samples.go @@ -0,0 +1,37 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG502 - Blocklisted import DES + SampleCodeG502 = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/cipher" + "crypto/des" + "crypto/rand" + "encoding/hex" + "fmt" + "io" +) + +func main() { + block, err := des.NewCipher([]byte("sekritz")) + if err != nil { + panic(err) + } + plaintext := []byte("I CAN HAZ SEKRIT MSG PLZ") + ciphertext := make([]byte, des.BlockSize+len(plaintext)) + iv := ciphertext[:des.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic(err) + } + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(ciphertext[des.BlockSize:], plaintext) + fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext)) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g503_samples.go b/testutils/g503_samples.go new file mode 100644 index 0000000..0732ab7 --- /dev/null +++ b/testutils/g503_samples.go @@ -0,0 +1,29 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG503 - Blocklisted import RC4 + SampleCodeG503 = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/rc4" + "encoding/hex" + "fmt" +) + +func main() { + cipher, err := rc4.NewCipher([]byte("sekritz")) + if err != nil { + panic(err) + } + plaintext := []byte("I CAN HAZ SEKRIT MSG PLZ") + ciphertext := make([]byte, len(plaintext)) + cipher.XORKeyStream(ciphertext, plaintext) + fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext)) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g504_samples.go b/testutils/g504_samples.go new file mode 100644 index 0000000..dd96b6f --- /dev/null +++ b/testutils/g504_samples.go @@ -0,0 +1,21 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG504 - Blocklisted import CGI + SampleCodeG504 = []CodeSample{ + {[]string{` +package main + +import ( + "net/http/cgi" + "net/http" + ) + +func main() { + cgi.Serve(http.FileServer(http.Dir("/usr/share/doc"))) +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g505_samples.go b/testutils/g505_samples.go new file mode 100644 index 0000000..cc2379c --- /dev/null +++ b/testutils/g505_samples.go @@ -0,0 +1,24 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG505 - Blocklisted import SHA1 + SampleCodeG505 = []CodeSample{ + {[]string{` +package main + +import ( + "crypto/sha1" + "fmt" + "os" +) + +func main() { + for _, arg := range os.Args { + fmt.Printf("%x - %s\n", sha1.Sum([]byte(arg)), arg) + } +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g601_samples.go b/testutils/g601_samples.go new file mode 100644 index 0000000..f6dfc02 --- /dev/null +++ b/testutils/g601_samples.go @@ -0,0 +1,221 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG601 - Implicit aliasing over range statement + SampleCodeG601 = []CodeSample{ + {[]string{` +package main + +import "fmt" + +var vector []*string +func appendVector(s *string) { + vector = append(vector, s) +} + +func printVector() { + for _, item := range vector { + fmt.Printf("%s", *item) + } + fmt.Println() +} + +func foo() (int, **string, *string) { + for _, item := range vector { + return 0, &item, item + } + return 0, nil, nil +} + +func main() { + for _, item := range []string{"A", "B", "C"} { + appendVector(&item) + } + + printVector() + + zero, c_star, c := foo() + fmt.Printf("%d %v %s", zero, c_star, c) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +// see: github.com/securego/gosec/issues/475 +package main + +import ( + "fmt" +) + +func main() { + sampleMap := map[string]string{} + sampleString := "A string" + for sampleString, _ = range sampleMap { + fmt.Println(sampleString) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +type sampleStruct struct { + name string +} + +func main() { + samples := []sampleStruct{ + {name: "a"}, + {name: "b"}, + } + for _, sample := range samples { + fmt.Println(sample.name) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +type sampleStruct struct { + name string +} + +func main() { + samples := []*sampleStruct{ + {name: "a"}, + {name: "b"}, + } + for _, sample := range samples { + fmt.Println(&sample) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +type sampleStruct struct { + name string +} + +func main() { + samples := []*sampleStruct{ + {name: "a"}, + {name: "b"}, + } + for _, sample := range samples { + fmt.Println(&sample.name) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +type sampleStruct struct { + name string +} + +func main() { + samples := []sampleStruct{ + {name: "a"}, + {name: "b"}, + } + for _, sample := range samples { + fmt.Println(&sample.name) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +type subStruct struct { + name string +} + +type sampleStruct struct { + sub subStruct +} + +func main() { + samples := []sampleStruct{ + {sub: subStruct{name: "a"}}, + {sub: subStruct{name: "b"}}, + } + for _, sample := range samples { + fmt.Println(&sample.sub.name) + } +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +type subStruct struct { + name string +} + +type sampleStruct struct { + sub subStruct +} + +func main() { + samples := []*sampleStruct{ + {sub: subStruct{name: "a"}}, + {sub: subStruct{name: "b"}}, + } + for _, sample := range samples { + fmt.Println(&sample.sub.name) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import ( + "fmt" +) + +func main() { + one, two := 1, 2 + samples := []*int{&one, &two} + for _, sample := range samples { + fmt.Println(&sample) + } +} +`}, 1, gosec.NewConfig()}, + } + + // SampleCodeBuildTag - G601 build tags + SampleCodeBuildTag = []CodeSample{ + {[]string{` +// +build tag +package main + +func main() { + fmt.Println("no package imported error") +} +`}, 1, gosec.NewConfig()}, + } +) diff --git a/testutils/g602_samples.go b/testutils/g602_samples.go new file mode 100644 index 0000000..65394b9 --- /dev/null +++ b/testutils/g602_samples.go @@ -0,0 +1,255 @@ +package testutils + +import "github.com/securego/gosec/v2" + +var ( + // SampleCodeG602 - Slice access out of bounds + SampleCodeG602 = []CodeSample{ + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 0) + + fmt.Println(s[:3]) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 0) + + fmt.Println(s[3:]) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 16) + + fmt.Println(s[:17]) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 16) + + fmt.Println(s[:16]) + +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 16) + + fmt.Println(s[5:17]) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 4) + + fmt.Println(s[3]) + +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 4) + + fmt.Println(s[5]) + +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 0) + s = make([]byte, 3) + + fmt.Println(s[:3]) + +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 0, 4) + + fmt.Println(s[:3]) + fmt.Println(s[3]) + +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 0, 4) + + fmt.Println(s[:5]) + fmt.Println(s[7]) + +} +`}, 2, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]byte, 0, 4) + x := s[:2] + y := x[:10] + fmt.Println(y) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]int, 0, 4) + doStuff(s) +} + +func doStuff(x []int) { + newSlice := x[:10] + fmt.Println(newSlice) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + + s := make([]int, 0, 30) + doStuff(s) + x := make([]int, 20) + y := x[10:] + doStuff(y) + z := y[5:] + doStuff(z) +} + +func doStuff(x []int) { + newSlice := x[:10] + fmt.Println(newSlice) + newSlice2 := x[:6] + fmt.Println(newSlice2) +} +`}, 2, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + testMap := make(map[string]any, 0) + testMap["test1"] = map[string]interface{}{ + "test2": map[string]interface{}{ + "value": 0, + }, + } + fmt.Println(testMap) +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + s := make([]byte, 0) + if len(s) > 0 { + fmt.Println(s[0]) + } +} +`}, 0, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + s := make([]byte, 0) + if len(s) > 0 { + fmt.Println("fake test") + } + fmt.Println(s[0]) +} +`}, 1, gosec.NewConfig()}, + {[]string{` +package main + +import "fmt" + +func main() { + s := make([]int, 16) + for i := 0; i < 17; i++ { + s = append(s, i) + } + if len(s) < 16 { + fmt.Println(s[10:16]) + } else { + fmt.Println(s[3:18]) + } + fmt.Println(s[0]) + for i := range s { + fmt.Println(s[i]) + } +} +`}, 0, gosec.NewConfig()}, + } +) diff --git a/testutils/sample_types.go b/testutils/sample_types.go new file mode 100644 index 0000000..f99159a --- /dev/null +++ b/testutils/sample_types.go @@ -0,0 +1,10 @@ +package testutils + +import "github.com/securego/gosec/v2" + +// CodeSample encapsulates a snippet of source code that compiles, and how many errors should be detected +type CodeSample struct { + Code []string + Errors int + Config gosec.Config +} diff --git a/testutils/source.go b/testutils/source.go deleted file mode 100644 index 2bb03e7..0000000 --- a/testutils/source.go +++ /dev/null @@ -1,4076 +0,0 @@ -package testutils - -import "github.com/securego/gosec/v2" - -// CodeSample encapsulates a snippet of source code that compiles, and how many errors should be detected -type CodeSample struct { - Code []string - Errors int - Config gosec.Config -} - -var ( - // SampleCodeG101 code snippets for hardcoded credentials - SampleCodeG101 = []CodeSample{ - {[]string{` -package main - -import "fmt" - -func main() { - username := "admin" - password := "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" - fmt.Println("Doing something with: ", username, password) -}`}, 1, gosec.NewConfig()}, - {[]string{` -// Entropy check should not report this error by default -package main - -import "fmt" - -func main() { - username := "admin" - password := "secret" - fmt.Println("Doing something with: ", username, password) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -var password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" - -func main() { - username := "admin" - fmt.Println("Doing something with: ", username, password) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -const password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" - -func main() { - username := "admin" - fmt.Println("Doing something with: ", username, password) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -const ( - username = "user" - password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" -) - -func main() { - fmt.Println("Doing something with: ", username, password) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -var password string - -func init() { - password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -const ( - ATNStateSomethingElse = 1 - ATNStateTokenStart = 42 -) - -func main() { - println(ATNStateTokenStart) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -const ( - ATNStateTokenStart = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" -) - -func main() { - println(ATNStateTokenStart) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - var password string - if password == "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { - fmt.Println("password equality") - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - var password string - if "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" == password { - fmt.Println("password equality") - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - var password string - if password != "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { - fmt.Println("password equality") - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - var password string - if "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" != password { - fmt.Println("password equality") - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - var p string - if p != "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" { - fmt.Println("password equality") - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - var p string - if "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" != p { - fmt.Println("password equality") - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -const ( - pw = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" -) - -func main() { - fmt.Println(pw) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -var ( - pw string -) - -func main() { - pw = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" - fmt.Println(pw) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -const ( - cred = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" -) - -func main() { - fmt.Println(cred) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -var ( - cred string -) - -func main() { - cred = "KjasdlkjapoIKLlka98098sdf012U/rL2sLdBqOHQUlt5Z6kCgKGDyCFA==" - fmt.Println(cred) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -const ( - apiKey = "KjasdlkjapoIKLlka98098sdf012U" -) - -func main() { - fmt.Println(apiKey) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -var ( - apiKey string -) - -func main() { - apiKey = "KjasdlkjapoIKLlka98098sdf012U" - fmt.Println(apiKey) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -const ( - bearer = "Bearer: 2lkjdfoiuwer092834kjdwf09" -) - -func main() { - fmt.Println(bearer) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -var ( - bearer string -) - -func main() { - bearer = "Bearer: 2lkjdfoiuwer092834kjdwf09" - fmt.Println(bearer) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG101Values code snippets for hardcoded credentials - SampleCodeG101Values = []CodeSample{ - {[]string{` -package main - -import "fmt" - -func main() { - customerNameEnvKey := "FOO_CUSTOMER_NAME" - fmt.Println(customerNameEnvKey) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - txnID := "3637cfcc1eec55a50f78a7c435914583ccbc75a21dec9a0e94dfa077647146d7" - fmt.Println(txnID) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - urlSecret := "https://username:abcdef0123456789abcdef0123456789abcdef01@contoso.com/" - fmt.Println(urlSecret) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - githubToken := "ghp_iR54dhCYg9Tfmoywi9xLmmKZrrnAw438BYh3" - fmt.Println(githubToken) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - awsAccessKeyID := "AKIAI44QH8DHBEXAMPLE" - fmt.Println(awsAccessKeyID) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - compareGoogleAPI := "test" - if compareGoogleAPI == "AIzajtGS_aJGkoiAmSbXzu9I-1eytAi9Lrlh-vT" { - fmt.Println(compareGoogleAPI) - } -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG102 code snippets for network binding - SampleCodeG102 = []CodeSample{ - // Bind to all networks explicitly - {[]string{` -package main - -import ( - "log" - "net" -) - -func main() { - l, err := net.Listen("tcp", "0.0.0.0:2000") - if err != nil { - log.Fatal(err) - } - defer l.Close() -}`}, 1, gosec.NewConfig()}, - - // Bind to all networks implicitly (default if host omitted) - {[]string{` -package main - -import ( - "log" - "net" -) - -func main() { - l, err := net.Listen("tcp", ":2000") - if err != nil { - log.Fatal(err) - } - defer l.Close() -}`}, 1, gosec.NewConfig()}, - // Bind to all networks indirectly through a parsing function - {[]string{` -package main - -import ( - "log" - "net" -) - -func parseListenAddr(listenAddr string) (network string, addr string) { - return "", "" -} - -func main() { - addr := ":2000" - l, err := net.Listen(parseListenAddr(addr)) - if err != nil { - log.Fatal(err) - } - defer l.Close() -}`}, 1, gosec.NewConfig()}, - // Bind to all networks indirectly through a parsing function - {[]string{` -package main - -import ( - "log" - "net" -) - -const addr = ":2000" - -func parseListenAddr(listenAddr string) (network string, addr string) { - return "", "" -} - -func main() { - l, err := net.Listen(parseListenAddr(addr)) - if err != nil { - log.Fatal(err) - } - defer l.Close() -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "log" - "net" -) - -const addr = "0.0.0.0:2000" - -func main() { - l, err := net.Listen("tcp", addr) - if err != nil { - log.Fatal(err) - } - defer l.Close() -}`}, 1, gosec.NewConfig()}, - } - // SampleCodeG103 find instances of unsafe blocks for auditing purposes - SampleCodeG103 = []CodeSample{ - {[]string{` -package main - -import ( - "fmt" - "unsafe" -) - -type Fake struct{} - -func (Fake) Good() {} - -func main() { - unsafeM := Fake{} - unsafeM.Good() - intArray := [...]int{1, 2} - fmt.Printf("\nintArray: %v\n", intArray) - intPtr := &intArray[0] - fmt.Printf("\nintPtr=%p, *intPtr=%d.\n", intPtr, *intPtr) - addressHolder := uintptr(unsafe.Pointer(intPtr)) - intPtr = (*int)(unsafe.Pointer(addressHolder)) - fmt.Printf("\nintPtr=%p, *intPtr=%d.\n\n", intPtr, *intPtr) -}`}, 2, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "unsafe" -) - -func main() { - chars := [...]byte{1, 2} - charsPtr := &chars[0] - str := unsafe.String(charsPtr, len(chars)) - fmt.Printf("%s\n", str) - ptr := unsafe.StringData(str) - fmt.Printf("ptr: %p\n", ptr) - -}`}, 2, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "unsafe" -) - -func main() { - chars := [...]byte{1, 2} - charsPtr := &chars[0] - slice := unsafe.Slice(charsPtr, len(chars)) - fmt.Printf("%v\n", slice) - ptr := unsafe.SliceData(slice) - fmt.Printf("ptr: %p\n", ptr) -}`}, 2, gosec.NewConfig()}, - } - - // SampleCodeG104 finds errors that aren't being handled - SampleCodeG104 = []CodeSample{ - {[]string{` -package main - -import "fmt" - -func test() (int,error) { - return 0, nil -} - -func main() { - v, _ := test() - fmt.Println(v) -}`}, 0, gosec.NewConfig()}, {[]string{` -package main - -import ( - "io/ioutil" - "os" - "fmt" -) - -func a() error { - return fmt.Errorf("This is an error") -} - -func b() { - fmt.Println("b") - ioutil.WriteFile("foo.txt", []byte("bar"), os.ModeExclusive) -} - -func c() string { - return fmt.Sprintf("This isn't anything") -} - -func main() { - _ = a() - a() - b() - c() -}`}, 2, gosec.NewConfig()}, {[]string{` -package main - -import "fmt" - -func test() error { - return nil -} - -func main() { - e := test() - fmt.Println(e) -}`}, 0, gosec.NewConfig()}, {[]string{` -// +build go1.10 - -package main - -import "strings" - -func main() { - var buf strings.Builder - _, err := buf.WriteString("test string") - if err != nil { - panic(err) - } -}`, ` -package main - -func dummy(){} -`}, 0, gosec.NewConfig()}, {[]string{` -package main - -import ( - "bytes" -) - -type a struct { - buf *bytes.Buffer -} - -func main() { - a := &a{ - buf: new(bytes.Buffer), - } - a.buf.Write([]byte{0}) -} -`}, 0, gosec.NewConfig()}, {[]string{` -package main - -import ( - "io/ioutil" - "os" - "fmt" -) - -func a() { - fmt.Println("a") - ioutil.WriteFile("foo.txt", []byte("bar"), os.ModeExclusive) -} - -func main() { - a() -}`}, 0, gosec.Config{"G104": map[string]interface{}{"ioutil": []interface{}{"WriteFile"}}}}, {[]string{` -package main - -import ( - "bytes" - "fmt" - "io" - "os" - "strings" -) - -func createBuffer() *bytes.Buffer { - return new(bytes.Buffer) -} - -func main() { - new(bytes.Buffer).WriteString("*bytes.Buffer") - fmt.Fprintln(os.Stderr, "fmt") - new(strings.Builder).WriteString("*strings.Builder") - _, pw := io.Pipe() - pw.CloseWithError(io.EOF) - - createBuffer().WriteString("*bytes.Buffer") - b := createBuffer() - b.WriteString("*bytes.Buffer") -}`}, 0, gosec.NewConfig()}, - } // it shouldn't return any errors because all method calls are whitelisted by default - - // SampleCodeG104Audit finds errors that aren't being handled in audit mode - SampleCodeG104Audit = []CodeSample{ - {[]string{` -package main - -import "fmt" - -func test() (int,error) { - return 0, nil -} - -func main() { - v, _ := test() - fmt.Println(v) -}`}, 1, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, {[]string{` -package main - -import ( - "io/ioutil" - "os" - "fmt" -) - -func a() error { - return fmt.Errorf("This is an error") -} - -func b() { - fmt.Println("b") - ioutil.WriteFile("foo.txt", []byte("bar"), os.ModeExclusive) -} - -func c() string { - return fmt.Sprintf("This isn't anything") -} - -func main() { - _ = a() - a() - b() - c() -}`}, 3, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, {[]string{` -package main - -import "fmt" - -func test() error { - return nil -} - -func main() { - e := test() - fmt.Println(e) -}`}, 0, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, {[]string{` -// +build go1.10 - -package main - -import "strings" - -func main() { - var buf strings.Builder - _, err := buf.WriteString("test string") - if err != nil { - panic(err) - } -}`, ` -package main - -func dummy(){} -`}, 0, gosec.Config{gosec.Globals: map[gosec.GlobalOption]string{gosec.Audit: "enabled"}}}, - } - - // SampleCodeG106 - ssh InsecureIgnoreHostKey - SampleCodeG106 = []CodeSample{{[]string{` -package main - -import ( - "golang.org/x/crypto/ssh" -) - -func main() { - _ = ssh.InsecureIgnoreHostKey() -}`}, 1, gosec.NewConfig()}} - - // SampleCodeG107 - SSRF via http requests with variable url - SampleCodeG107 = []CodeSample{{[]string{` -// Input from the std in is considered insecure -package main -import ( - "net/http" - "io/ioutil" - "fmt" - "os" - "bufio" -) -func main() { - in := bufio.NewReader(os.Stdin) - url, err := in.ReadString('\n') - if err != nil { - panic(err) - } - resp, err := http.Get(url) - if err != nil { - panic(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - panic(err) - } - fmt.Printf("%s", body) -}`}, 1, gosec.NewConfig()}, {[]string{` -// Variable defined a package level can be changed at any time -// regardless of the initial value -package main - -import ( - "fmt" - "io/ioutil" - "net/http" -) - -var url string = "https://www.google.com" - -func main() { - resp, err := http.Get(url) - if err != nil { - panic(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - panic(err) - } - fmt.Printf("%s", body) -}`}, 1, gosec.NewConfig()}, {[]string{` -// Environmental variables are not considered as secure source -package main -import ( - "net/http" - "io/ioutil" - "fmt" - "os" -) -func main() { - url := os.Getenv("tainted_url") - resp, err := http.Get(url) - if err != nil { - panic(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - panic(err) - } - fmt.Printf("%s", body) -}`}, 1, gosec.NewConfig()}, {[]string{` -// Constant variables or hard-coded strings are secure -package main - -import ( - "fmt" - "net/http" -) -const url = "http://127.0.0.1" -func main() { - resp, err := http.Get(url) - if err != nil { - fmt.Println(err) - } - fmt.Println(resp.Status) -}`}, 0, gosec.NewConfig()}, {[]string{` -// A variable at function scope which is initialized to -// a constant string is secure (e.g. cannot be changed concurrently) -package main - -import ( - "fmt" - "net/http" -) -func main() { - var url string = "http://127.0.0.1" - resp, err := http.Get(url) - if err != nil { - fmt.Println(err) - } - fmt.Println(resp.Status) -}`}, 0, gosec.NewConfig()}, {[]string{` -// A variable at function scope which is initialized to -// a constant string is secure (e.g. cannot be changed concurrently) -package main - -import ( - "fmt" - "net/http" -) -func main() { - url := "http://127.0.0.1" - resp, err := http.Get(url) - if err != nil { - fmt.Println(err) - } - fmt.Println(resp.Status) -}`}, 0, gosec.NewConfig()}, {[]string{` -// A variable at function scope which is initialized to -// a constant string is secure (e.g. cannot be changed concurrently) -package main - -import ( - "fmt" - "net/http" -) -func main() { - url1 := "test" - var url2 string = "http://127.0.0.1" - url2 = url1 - resp, err := http.Get(url2) - if err != nil { - fmt.Println(err) - } - fmt.Println(resp.Status) -}`}, 0, gosec.NewConfig()}, {[]string{` -// An exported variable declared a packaged scope is not secure -// because it can changed at any time -package main - -import ( - "fmt" - "net/http" -) - -var Url string - -func main() { - resp, err := http.Get(Url) - if err != nil { - fmt.Println(err) - } - fmt.Println(resp.Status) -}`}, 1, gosec.NewConfig()}, {[]string{` -// An url provided as a function argument is not secure -package main - -import ( - "fmt" - "net/http" -) -func get(url string) { - resp, err := http.Get(url) - if err != nil { - fmt.Println(err) - } - fmt.Println(resp.Status) -} -func main() { - url := "http://127.0.0.1" - get(url) -}`}, 1, gosec.NewConfig()}} - - // SampleCodeG108 - pprof endpoint automatically exposed - SampleCodeG108 = []CodeSample{{[]string{` -package main - -import ( - "fmt" - "log" - "net/http" - _ "net/http/pprof" -) - -func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello World!") - }) - log.Fatal(http.ListenAndServe(":8080", nil)) -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "fmt" - "log" - "net/http" -) - -func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello World!") - }) - log.Fatal(http.ListenAndServe(":8080", nil)) -}`}, 0, gosec.NewConfig()}} - - // SampleCodeG109 - Potential Integer OverFlow - SampleCodeG109 = []CodeSample{ - {[]string{` -package main - -import ( - "fmt" - "strconv" -) - -func main() { - bigValue, err := strconv.Atoi("2147483648") - if err != nil { - panic(err) - } - value := int32(bigValue) - fmt.Println(value) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "strconv" -) - -func main() { - bigValue, err := strconv.Atoi("32768") - if err != nil { - panic(err) - } - if int16(bigValue) < 0 { - fmt.Println(bigValue) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "strconv" -) - -func main() { - bigValue, err := strconv.Atoi("2147483648") - if err != nil { - panic(err) - } - fmt.Println(bigValue) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "strconv" -) - -func main() { - bigValue, err := strconv.Atoi("2147483648") - if err != nil { - panic(err) - } - fmt.Println(bigValue) - test() -} - -func test() { - bigValue := 30 - value := int32(bigValue) - fmt.Println(value) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "strconv" -) - -func main() { - value := 10 - if value == 10 { - value, _ := strconv.Atoi("2147483648") - fmt.Println(value) - } - v := int32(value) - fmt.Println(v) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main -import ( - "fmt" - "strconv" -) -func main() { - a, err := strconv.Atoi("a") - b := int32(a) //#nosec G109 - fmt.Println(b, err) -}`}, 0, gosec.NewConfig()}, - } - - // SampleCodeG110 - potential DoS vulnerability via decompression bomb - SampleCodeG110 = []CodeSample{ - {[]string{` -package main - -import ( - "bytes" - "compress/zlib" - "io" - "os" -) - -func main() { - buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207, - 47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147} - b := bytes.NewReader(buff) - - r, err := zlib.NewReader(b) - if err != nil { - panic(err) - } - _, err = io.Copy(os.Stdout, r) - if err != nil { - panic(err) - } - - r.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "bytes" - "compress/zlib" - "io" - "os" -) - -func main() { - buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207, - 47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147} - b := bytes.NewReader(buff) - - r, err := zlib.NewReader(b) - if err != nil { - panic(err) - } - buf := make([]byte, 8) - _, err = io.CopyBuffer(os.Stdout, r, buf) - if err != nil { - panic(err) - } - r.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "archive/zip" - "io" - "os" - "strconv" -) - -func main() { - r, err := zip.OpenReader("tmp.zip") - if err != nil { - panic(err) - } - defer r.Close() - - for i, f := range r.File { - out, err := os.OpenFile("output" + strconv.Itoa(i), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) - if err != nil { - panic(err) - } - - rc, err := f.Open() - if err != nil { - panic(err) - } - - _, err = io.Copy(out, rc) - - out.Close() - rc.Close() - - if err != nil { - panic(err) - } - } -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "io" - "os" -) - -func main() { - s, err := os.Open("src") - if err != nil { - panic(err) - } - defer s.Close() - - d, err := os.Create("dst") - if err != nil { - panic(err) - } - defer d.Close() - - _, err = io.Copy(d, s) - if err != nil { - panic(err) - } -}`}, 0, gosec.NewConfig()}, - } - - // SampleCodeG111 - potential directory traversal - SampleCodeG111 = []CodeSample{ - {[]string{` -package main - -import ( - "fmt" - "log" - "net/http" - "os" -) - -func main() { - http.Handle("/bad/", http.StripPrefix("/bad/", http.FileServer(http.Dir("/")))) - http.HandleFunc("/", HelloServer) - log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil)) -} - -func HelloServer(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG112 - potential slowloris attack - SampleCodeG112 = []CodeSample{ - {[]string{` - package main - - import ( - "fmt" - "net/http" - ) - - func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) - }) - err := (&http.Server{ - Addr: ":1234", - }).ListenAndServe() - if err != nil { - panic(err) - } - } - `}, 1, gosec.NewConfig()}, - {[]string{` - package main - - import ( - "fmt" - "time" - "net/http" - ) - - func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) - }) - server := &http.Server{ - Addr: ":1234", - ReadHeaderTimeout: 3 * time.Second, - } - err := server.ListenAndServe() - if err != nil { - panic(err) - } - } - `}, 0, gosec.NewConfig()}, - {[]string{` - package main - - import ( - "fmt" - "time" - "net/http" - ) - - func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) - }) - server := &http.Server{ - Addr: ":1234", - ReadTimeout: 1 * time.Second, - } - err := server.ListenAndServe() - if err != nil { - panic(err) - } - } - `}, 0, gosec.NewConfig()}, - {[]string{` - package main - - import ( - "fmt" - "net/http" - "sync" - ) - - type Server struct { - hs *http.Server - mux *http.ServeMux - mu sync.Mutex - } - - func New(listenAddr string) *Server { - mux := http.NewServeMux() - - return &Server{ - hs: &http.Server{ // #nosec G112 - Not publicly exposed - Addr: listenAddr, - Handler: mux, - }, - mux: mux, - mu: sync.Mutex{}, - } - } - - func main() { - fmt.Print("test") - } - `}, 0, gosec.NewConfig()}, - } - - // SampleCodeG113 - Usage of Rat.SetString in math/big with an overflow - SampleCodeG113 = []CodeSample{ - {[]string{ - ` -package main - -import ( - "math/big" - "fmt" -) - -func main() { - r := big.Rat{} - r.SetString("13e-9223372036854775808") - - fmt.Println(r) -}`, - }, 1, gosec.NewConfig()}, - } - - // SampleCodeG114 - Use of net/http serve functions that have no support for setting timeouts - SampleCodeG114 = []CodeSample{ - {[]string{ - ` -package main - -import ( - "log" - "net/http" -) - -func main() { - err := http.ListenAndServe(":8080", nil) - log.Fatal(err) -}`, - }, 1, gosec.NewConfig()}, - { - []string{ - ` -package main - -import ( - "log" - "net/http" -) - -func main() { - err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil) - log.Fatal(err) -}`, - }, 1, gosec.NewConfig(), - }, - { - []string{ - ` -package main - -import ( - "log" - "net" - "net/http" -) - -func main() { - l, err := net.Listen("tcp", ":8080") - if err != nil { - log.Fatal(err) - } - defer l.Close() - err = http.Serve(l, nil) - log.Fatal(err) -}`, - }, 1, gosec.NewConfig(), - }, - { - []string{ - ` -package main - -import ( - "log" - "net" - "net/http" -) - -func main() { - l, err := net.Listen("tcp", ":8443") - if err != nil { - log.Fatal(err) - } - defer l.Close() - err = http.ServeTLS(l, nil, "cert.pem", "key.pem") - log.Fatal(err) -}`, - }, 1, gosec.NewConfig(), - }, - } - - // SampleCodeG201 - SQL injection via format string - SampleCodeG201 = []CodeSample{ - {[]string{` -// Format string without proper quoting -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT * FROM foo where name = '%s'", os.Args[1]) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// Format string without proper quoting case insensitive -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("select * from foo where name = '%s'", os.Args[1]) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// Format string without proper quoting with context -package main -import ( - "context" - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("select * from foo where name = '%s'", os.Args[1]) - rows, err := db.QueryContext(context.Background(), q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// Format string without proper quoting with transaction -package main -import ( - "context" - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - tx, err := db.Begin() - if err != nil { - panic(err) - } - defer tx.Rollback() - q := fmt.Sprintf("select * from foo where name = '%s'", os.Args[1]) - rows, err := tx.QueryContext(context.Background(), q) - if err != nil { - panic(err) - } - defer rows.Close() - if err := tx.Commit(); err != nil { - panic(err) - } -}`}, 1, gosec.NewConfig()}, {[]string{` -// Format string false positive, safe string spec. -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT * FROM foo where id = %d", os.Args[1]) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 0, gosec.NewConfig()}, {[]string{` -// Format string false positive -package main - -import ( - "database/sql" -) - -const staticQuery = "SELECT * FROM foo WHERE age < 32" - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query(staticQuery) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 0, gosec.NewConfig()}, {[]string{` -// Format string false positive, quoted formatter argument. -package main - -import ( - "database/sql" - "fmt" - "os" - "github.com/lib/pq" -) - -func main(){ - db, err := sql.Open("postgres", "localhost") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT * FROM %s where id = 1", pq.QuoteIdentifier(os.Args[1])) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 0, gosec.NewConfig()}, {[]string{` -// false positive -package main - -import ( - "database/sql" - "fmt" -) - -const Table = "foo" -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT * FROM %s where id = 1", Table) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 0, gosec.NewConfig()}, {[]string{` -package main -import ( - "fmt" -) - -func main(){ - fmt.Sprintln() -}`}, 0, gosec.NewConfig()}, {[]string{` -// Format string with \n\r -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT * FROM foo where\n name = '%s'", os.Args[1]) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// Format string with \n\r -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT * FROM foo where\nname = '%s'", os.Args[1]) - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// SQLI by db.Query(some).Scan(&other) -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main() { - var name string - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT name FROM users where id = '%s'", os.Args[1]) - row := db.QueryRow(q) - err = row.Scan(&name) - if err != nil { - panic(err) - } - defer db.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// SQLI by db.Query(some).Scan(&other) -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main() { - var name string - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT name FROM users where id = '%s'", os.Args[1]) - err = db.QueryRow(q).Scan(&name) - if err != nil { - panic(err) - } - defer db.Close() -}`}, 1, gosec.NewConfig()}, {[]string{` -// SQLI by db.Prepare(some) -package main - -import ( - "database/sql" - "fmt" - "log" - "os" -) - -const Table = "foo" - -func main() { - var album string - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT name FROM users where '%s' = ?", os.Args[1]) - stmt, err := db.Prepare(q) - if err != nil { - log.Fatal(err) - } - stmt.QueryRow(fmt.Sprintf("%s", os.Args[2])).Scan(&album) - if err != nil { - if err == sql.ErrNoRows { - log.Fatal(err) - } - } - defer stmt.Close() -} -`}, 1, gosec.NewConfig()}, {[]string{` -// SQLI by db.PrepareContext(some) -package main - -import ( - "context" - "database/sql" - "fmt" - "log" - "os" -) - -const Table = "foo" - -func main() { - var album string - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - q := fmt.Sprintf("SELECT name FROM users where '%s' = ?", os.Args[1]) - stmt, err := db.PrepareContext(context.Background(), q) - if err != nil { - log.Fatal(err) - } - stmt.QueryRow(fmt.Sprintf("%s", os.Args[2])).Scan(&album) - if err != nil { - if err == sql.ErrNoRows { - log.Fatal(err) - } - } - defer stmt.Close() -} -`}, 1, gosec.NewConfig()}, {[]string{` -// false positive -package main - -import ( - "database/sql" - "fmt" - "log" - "os" -) - -const Table = "foo" - -func main() { - var album string - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - stmt, err := db.Prepare("SELECT * FROM album WHERE id = ?") - if err != nil { - log.Fatal(err) - } - stmt.QueryRow(fmt.Sprintf("%s", os.Args[1])).Scan(&album) - if err != nil { - if err == sql.ErrNoRows { - log.Fatal(err) - } - } - defer stmt.Close() -} -`}, 0, gosec.NewConfig()}, - } - - // SampleCodeG202 - SQL query string building via string concatenation - SampleCodeG202 = []CodeSample{ - {[]string{` - // infixed concatenation -package main - -import ( - "database/sql" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - - q := "INSERT INTO foo (name) VALUES ('" + os.Args[0] + "')" - rows, err := db.Query(q) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "database/sql" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query("SELECT * FROM foo WHERE name = " + os.Args[1]) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, - {[]string{` -// case insensitive match -package main - -import ( - "database/sql" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query("select * from foo where name = " + os.Args[1]) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, - {[]string{` -// context match -package main - -import ( - "context" - "database/sql" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.QueryContext(context.Background(), "select * from foo where name = " + os.Args[1]) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, - {[]string{` -// DB transaction check -package main - -import ( - "context" - "database/sql" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - tx, err := db.Begin() - if err != nil { - panic(err) - } - defer tx.Rollback() - rows, err := tx.QueryContext(context.Background(), "select * from foo where name = " + os.Args[1]) - if err != nil { - panic(err) - } - defer rows.Close() - if err := tx.Commit(); err != nil { - panic(err) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -// multiple string concatenation -package main - -import ( - "database/sql" - "os" -) - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query("SELECT * FROM foo" + "WHERE name = " + os.Args[1]) - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 1, gosec.NewConfig()}, - {[]string{` -// false positive -package main - -import ( - "database/sql" -) - -var staticQuery = "SELECT * FROM foo WHERE age < " -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query(staticQuery + "32") - if err != nil { - panic(err) - } - defer rows.Close() -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "database/sql" -) - -const age = "32" - -var staticQuery = "SELECT * FROM foo WHERE age < " - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query(staticQuery + age) - if err != nil { - panic(err) - } - defer rows.Close() -} -`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -const gender = "M" -`, ` -package main - -import ( - "database/sql" -) - -const age = "32" - -var staticQuery = "SELECT * FROM foo WHERE age < " - -func main(){ - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - rows, err := db.Query("SELECT * FROM foo WHERE gender = " + gender) - if err != nil { - panic(err) - } - defer rows.Close() -} -`}, 0, gosec.NewConfig()}, - {[]string{` -// ExecContext match -package main - -import ( - "context" - "database/sql" - "fmt" - "os" -) - -func main() { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - result, err := db.ExecContext(context.Background(), "select * from foo where name = "+os.Args[1]) - if err != nil { - panic(err) - } - fmt.Println(result) -}`}, 1, gosec.NewConfig()}, - {[]string{` -// Exec match -package main - -import ( - "database/sql" - "fmt" - "os" -) - -func main() { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - result, err := db.Exec("select * from foo where name = " + os.Args[1]) - if err != nil { - panic(err) - } - fmt.Println(result) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "database/sql" - "fmt" -) -const gender = "M" -const age = "32" - -var staticQuery = "SELECT * FROM foo WHERE age < " - -func main() { - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - panic(err) - } - result, err := db.Exec("SELECT * FROM foo WHERE gender = " + gender) - if err != nil { - panic(err) - } - fmt.Println(result) -} -`}, 0, gosec.NewConfig()}, - } - - // SampleCodeG203 - Template checks - SampleCodeG203 = []CodeSample{ - {[]string{` -// We assume that hardcoded template strings are safe as the programmer would -// need to be explicitly shooting themselves in the foot (as below) -package main - -import ( - "html/template" - "os" -) - -const tmpl = "" - -func main() { - t := template.Must(template.New("ex").Parse(tmpl)) - v := map[string]interface{}{ - "Title": "Test World", - "Body": template.HTML(""), - } - t.Execute(os.Stdout, v) -}`}, 0, gosec.NewConfig()}, {[]string{ - ` -// Using a variable to initialize could potentially be dangerous. Under the -// current model this will likely produce some false positives. -package main - -import ( - "html/template" - "os" -) - -const tmpl = "" - -func main() { - a := "something from another place" - t := template.Must(template.New("ex").Parse(tmpl)) - v := map[string]interface{}{ - "Title": "Test World", - "Body": template.HTML(a), - } - t.Execute(os.Stdout, v) -}`, - }, 1, gosec.NewConfig()}, {[]string{ - ` -package main - -import ( - "html/template" - "os" -) - -const tmpl = "" - -func main() { - a := "something from another place" - t := template.Must(template.New("ex").Parse(tmpl)) - v := map[string]interface{}{ - "Title": "Test World", - "Body": template.JS(a), - } - t.Execute(os.Stdout, v) -}`, - }, 1, gosec.NewConfig()}, {[]string{ - ` -package main - -import ( - "html/template" - "os" -) - -const tmpl = "" - -func main() { - a := "something from another place" - t := template.Must(template.New("ex").Parse(tmpl)) - v := map[string]interface{}{ - "Title": "Test World", - "Body": template.URL(a), - } - t.Execute(os.Stdout, v) -}`, - }, 1, gosec.NewConfig()}, - } - - // SampleCodeG204 - Subprocess auditing - SampleCodeG204 = []CodeSample{ - {[]string{` -package main - -import ( - "log" - "os/exec" - "context" -) - -func main() { - err := exec.CommandContext(context.Background(), "git", "rev-parse", "--show-toplevel").Run() - if err != nil { - log.Fatal(err) - } - log.Printf("Command finished with error: %v", err) -}`}, 0, gosec.NewConfig()}, - {[]string{` -// Calling any function which starts a new process with using -// command line arguments as it's arguments is considered dangerous -package main - -import ( - "context" - "log" - "os" - "os/exec" -) - -func main() { - err := exec.CommandContext(context.Background(), os.Args[0], "5").Run() - if err != nil { - log.Fatal(err) - } - log.Printf("Command finished with error: %v", err) -}`}, 1, gosec.NewConfig()}, - {[]string{` -// Initializing a local variable using a environmental -// variable is consider as a dangerous user input -package main - -import ( - "log" - "os" - "os/exec" -) - -func main() { - run := "sleep" + os.Getenv("SOMETHING") - cmd := exec.Command(run, "5") - err := cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() - log.Printf("Command finished with error: %v", err) -}`}, 1, gosec.NewConfig()}, - {[]string{` -// gosec doesn't have enough context to decide that the -// command argument of the RunCmd function is hardcoded string -// and that's why it's better to warn the user so he can audit it -package main - -import ( - "log" - "os/exec" -) - -func RunCmd(command string) { - cmd := exec.Command(command, "5") - err := cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() -} - -func main() { - RunCmd("sleep") -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "log" - "os/exec" -) - -func RunCmd(a string, c string) { - cmd := exec.Command(c) - err := cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() - - cmd = exec.Command(a) - err = cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() -} - -func main() { - RunCmd("ll", "ls") -}`}, 0, gosec.NewConfig()}, - {[]string{` -// syscall.Exec function called with hardcoded arguments -// shouldn't be consider as a command injection -package main - -import ( - "fmt" - "syscall" -) - -func main() { - err := syscall.Exec("/bin/cat", []string{"/etc/passwd"}, nil) - if err != nil { - fmt.Printf("Error: %v\n", err) - } -}`}, 0, gosec.NewConfig()}, - { - []string{` -package main - -import ( - "fmt" - "syscall" -) - -func RunCmd(command string) { - _, err := syscall.ForkExec(command, []string{}, nil) - if err != nil { - fmt.Printf("Error: %v\n", err) - } -} - -func main() { - RunCmd("sleep") -}`}, 1, gosec.NewConfig(), - }, - { - []string{` -package main - -import ( - "fmt" - "syscall" -) - -func RunCmd(command string) { - _, _, err := syscall.StartProcess(command, []string{}, nil) - if err != nil { - fmt.Printf("Error: %v\n", err) - } -} - -func main() { - RunCmd("sleep") -}`}, 1, gosec.NewConfig(), - }, - {[]string{` -// starting a process with a variable as an argument -// even if not constant is not considered as dangerous -// because it has hardcoded value -package main - -import ( - "log" - "os/exec" -) - -func main() { - run := "sleep" - cmd := exec.Command(run, "5") - err := cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() - log.Printf("Command finished with error: %v", err) -}`}, 0, gosec.NewConfig()}, - {[]string{` -// exec.Command from supplemental package sys/execabs -// using variable arguments -package main - -import ( - "context" - "log" - "os" - exec "golang.org/x/sys/execabs" -) - -func main() { - err := exec.CommandContext(context.Background(), os.Args[0], "5").Run() - if err != nil { - log.Fatal(err) - } - log.Printf("Command finished with error: %v", err) -} -`}, 1, gosec.NewConfig()}, - {[]string{` -// Initializing a local variable using a environmental -// variable is consider as a dangerous user input -package main - -import ( - "log" - "os" - "os/exec" -) - -func main() { - var run = "sleep" + os.Getenv("SOMETHING") - cmd := exec.Command(run, "5") - err := cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() - log.Printf("Command finished with error: %v", err) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG301 - mkdir permission check - SampleCodeG301 = []CodeSample{{[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - err := os.Mkdir("/tmp/mydir", 0777) - if err != nil { - fmt.Println("Error when creating a directory!") - return - } -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - err := os.MkdirAll("/tmp/mydir", 0777) - if err != nil { - fmt.Println("Error when creating a directory!") - return - } -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - err := os.Mkdir("/tmp/mydir", 0600) - if err != nil { - fmt.Println("Error when creating a directory!") - return - } -}`}, 0, gosec.NewConfig()}} - - // SampleCodeG302 - file create / chmod permissions check - SampleCodeG302 = []CodeSample{{[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - err := os.Chmod("/tmp/somefile", 0777) - if err != nil { - fmt.Println("Error when changing file permissions!") - return - } -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - _, err := os.OpenFile("/tmp/thing", os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - fmt.Println("Error opening a file!") - return - } -}`}, 1, gosec.NewConfig()}, {[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - err := os.Chmod("/tmp/mydir", 0400) - if err != nil { - fmt.Println("Error") - return - } -}`}, 0, gosec.NewConfig()}, {[]string{` -package main - -import ( - "fmt" - "os" -) - -func main() { - _, err := os.OpenFile("/tmp/thing", os.O_CREATE|os.O_WRONLY, 0600) - if err != nil { - fmt.Println("Error opening a file!") - return - } -} -`}, 0, gosec.NewConfig()}} - - // SampleCodeG303 - bad tempfile permissions & hardcoded shared path - SampleCodeG303 = []CodeSample{{[]string{` -package samples - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" -) - -func main() { - err := ioutil.WriteFile("/tmp/demo2", []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - f, err := os.Create("/tmp/demo2") - if err != nil { - fmt.Println("Error while writing!") - } else if err = f.Close(); err != nil { - fmt.Println("Error while closing!") - } - err = os.WriteFile("/tmp/demo2", []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - err = os.WriteFile("/usr/tmp/demo2", []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - err = os.WriteFile("/tmp/" + "demo2", []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - err = os.WriteFile(os.TempDir() + "/demo2", []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - err = os.WriteFile(path.Join("/var/tmp", "demo2"), []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - err = os.WriteFile(path.Join(os.TempDir(), "demo2"), []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } - err = os.WriteFile(filepath.Join(os.TempDir(), "demo2"), []byte("This is some data"), 0644) - if err != nil { - fmt.Println("Error while writing!") - } -}`}, 9, gosec.NewConfig()}} - - // SampleCodeG304 - potential file inclusion vulnerability - SampleCodeG304 = []CodeSample{ - {[]string{` -package main - -import ( -"os" -"io/ioutil" -"log" -) - -func main() { - f := os.Getenv("tainted_file") - body, err := ioutil.ReadFile(f) - if err != nil { - log.Printf("Error: %v\n", err) - } - log.Print(body) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( -"os" -"log" -) - -func main() { - f := os.Getenv("tainted_file") - body, err := os.ReadFile(f) - if err != nil { - log.Printf("Error: %v\n", err) - } - log.Print(body) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "log" - "net/http" - "os" -) - -func main() { - http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { - title := r.URL.Query().Get("title") - f, err := os.Open(title) - if err != nil { - fmt.Printf("Error: %v\n", err) - } - body := make([]byte, 5) - if _, err = f.Read(body); err != nil { - fmt.Printf("Error: %v\n", err) - } - fmt.Fprintf(w, "%s", body) - }) - log.Fatal(http.ListenAndServe(":3000", nil)) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "log" - "net/http" - "os" -) - -func main() { - http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) { - title := r.URL.Query().Get("title") - f, err := os.OpenFile(title, os.O_RDWR|os.O_CREATE, 0755) - if err != nil { - fmt.Printf("Error: %v\n", err) - } - body := make([]byte, 5) - if _, err = f.Read(body); err != nil { - fmt.Printf("Error: %v\n", err) - } - fmt.Fprintf(w, "%s", body) - }) - log.Fatal(http.ListenAndServe(":3000", nil)) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "log" - "os" - "io/ioutil" -) - - func main() { - f2 := os.Getenv("tainted_file2") - body, err := ioutil.ReadFile("/tmp/" + f2) - if err != nil { - log.Printf("Error: %v\n", err) - } - log.Print(body) - }`}, 1, gosec.NewConfig()}, - {[]string{` - package main - - import ( - "bufio" - "fmt" - "os" - "path/filepath" - ) - -func main() { - reader := bufio.NewReader(os.Stdin) - fmt.Print("Please enter file to read: ") - file, _ := reader.ReadString('\n') - file = file[:len(file)-1] - f, err := os.Open(filepath.Join("/tmp/service/", file)) - if err != nil { - fmt.Printf("Error: %v\n", err) - } - contents := make([]byte, 15) - if _, err = f.Read(contents); err != nil { - fmt.Printf("Error: %v\n", err) - } - fmt.Println(string(contents)) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "log" - "os" - "io/ioutil" - "path/filepath" -) - -func main() { - dir := os.Getenv("server_root") - f3 := os.Getenv("tainted_file3") - // edge case where both a binary expression and file Join are used. - body, err := ioutil.ReadFile(filepath.Join("/var/"+dir, f3)) - if err != nil { - log.Printf("Error: %v\n", err) - } - log.Print(body) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "os" - "path/filepath" -) - -func main() { - repoFile := "path_of_file" - cleanRepoFile := filepath.Clean(repoFile) - _, err := os.OpenFile(cleanRepoFile, os.O_RDONLY, 0600) - if err != nil { - panic(err) - } -} -`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "os" - "path/filepath" -) - -func openFile(filePath string) { - _, err := os.OpenFile(filepath.Clean(filePath), os.O_RDONLY, 0600) - if err != nil { - panic(err) - } -} - -func main() { - repoFile := "path_of_file" - openFile(repoFile) -} -`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "os" - "path/filepath" -) - -func openFile(dir string, filePath string) { - fp := filepath.Join(dir, filePath) - fp = filepath.Clean(fp) - _, err := os.OpenFile(fp, os.O_RDONLY, 0600) - if err != nil { - panic(err) - } -} - -func main() { - repoFile := "path_of_file" - dir := "path_of_dir" - openFile(dir, repoFile) -} -`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "os" - "path/filepath" -) - -func main() { - repoFile := "path_of_file" - relFile, err := filepath.Rel("./", repoFile) - if err != nil { - panic(err) - } - _, err = os.OpenFile(relFile, os.O_RDONLY, 0600) - if err != nil { - panic(err) - } -} - -`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "io" - "os" -) - -func createFile(file string) *os.File { - f, err := os.Create(file) - if err != nil { - panic(err) - } - return f -} - -func main() { - s, err := os.Open("src") - if err != nil { - panic(err) - } - defer s.Close() - - d := createFile("dst") - defer d.Close() - - _, err = io.Copy(d, s) - if err != nil { - panic(err) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" - "path/filepath" -) - -type foo struct { -} - -func (f *foo) doSomething(silly string) error { - whoCares, err := filepath.Rel(THEWD, silly) - if err != nil { - return err - } - fmt.Printf("%s", whoCares) - return nil -} - -func main() { - f := &foo{} - - if err := f.doSomething("irrelevant"); err != nil { - panic(err) - } -} -`, ` -package main - -var THEWD string -`}, 0, gosec.NewConfig()}, - } - - // SampleCodeG305 - File path traversal when extracting zip/tar archives - SampleCodeG305 = []CodeSample{{[]string{` -package unzip - -import ( - "archive/zip" - "io" - "os" - "path/filepath" -) - -func unzip(archive, target string) error { - reader, err := zip.OpenReader(archive) - if err != nil { - return err - } - - if err := os.MkdirAll(target, 0750); err != nil { - return err - } - - for _, file := range reader.File { - path := filepath.Join(target, file.Name) - if file.FileInfo().IsDir() { - os.MkdirAll(path, file.Mode()) //#nosec - continue - } - - fileReader, err := file.Open() - if err != nil { - return err - } - defer fileReader.Close() - - targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) - if err != nil { - return err - } - defer targetFile.Close() - - if _, err := io.Copy(targetFile, fileReader); err != nil { - return err - } - } - - return nil -}`}, 1, gosec.NewConfig()}, {[]string{` -package unzip - -import ( - "archive/zip" - "io" - "os" - "path/filepath" -) - -func unzip(archive, target string) error { - reader, err := zip.OpenReader(archive) - if err != nil { - return err - } - - if err := os.MkdirAll(target, 0750); err != nil { - return err - } - - for _, file := range reader.File { - archiveFile := file.Name - path := filepath.Join(target, archiveFile) - if file.FileInfo().IsDir() { - os.MkdirAll(path, file.Mode()) //#nosec - continue - } - - fileReader, err := file.Open() - if err != nil { - return err - } - defer fileReader.Close() - - targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) - if err != nil { - return err - } - defer targetFile.Close() - - if _, err := io.Copy(targetFile, fileReader); err != nil { - return err - } - } - - return nil -}`}, 1, gosec.NewConfig()}, {[]string{` -package zip - -import ( - "archive/zip" - "io" - "os" - "path" -) - -func extractFile(f *zip.File, destPath string) error { - filePath := path.Join(destPath, f.Name) - os.MkdirAll(path.Dir(filePath), os.ModePerm) - - rc, err := f.Open() - if err != nil { - return err - } - defer rc.Close() - - fw, err := os.Create(filePath) - if err != nil { - return err - } - defer fw.Close() - - if _, err = io.Copy(fw, rc); err != nil { - return err - } - - if f.FileInfo().Mode()&os.ModeSymlink != 0 { - return nil - } - - if err = os.Chtimes(filePath, f.ModTime(), f.ModTime()); err != nil { - return err - } - return os.Chmod(filePath, f.FileInfo().Mode()) -}`}, 1, gosec.NewConfig()}, {[]string{` -package tz - -import ( - "archive/tar" - "io" - "os" - "path" -) - -func extractFile(f *tar.Header, tr *tar.Reader, destPath string) error { - filePath := path.Join(destPath, f.Name) - os.MkdirAll(path.Dir(filePath), os.ModePerm) - - fw, err := os.Create(filePath) - if err != nil { - return err - } - defer fw.Close() - - if _, err = io.Copy(fw, tr); err != nil { - return err - } - - if f.FileInfo().Mode()&os.ModeSymlink != 0 { - return nil - } - - if err = os.Chtimes(filePath, f.FileInfo().ModTime(), f.FileInfo().ModTime()); err != nil { - return err - } - return os.Chmod(filePath, f.FileInfo().Mode()) -}`}, 1, gosec.NewConfig()}} - - // SampleCodeG306 - Poor permissions for WriteFile - SampleCodeG306 = []CodeSample{ - {[]string{`package main - -import ( - "bufio" - "fmt" - "io/ioutil" - "os" -) - -func check(e error) { - if e != nil { - panic(e) - } -} - -func main() { - - d1 := []byte("hello\ngo\n") - err := ioutil.WriteFile("/tmp/dat1", d1, 0744) - check(err) - - allowed := ioutil.WriteFile("/tmp/dat1", d1, 0600) - check(allowed) - - f, err := os.Create("/tmp/dat2") - check(err) - - defer f.Close() - - d2 := []byte{115, 111, 109, 101, 10} - n2, err := f.Write(d2) - - defer check(err) - fmt.Printf("wrote %d bytes\n", n2) - - n3, err := f.WriteString("writes\n") - fmt.Printf("wrote %d bytes\n", n3) - - f.Sync() - - w := bufio.NewWriter(f) - n4, err := w.WriteString("buffered\n") - fmt.Printf("wrote %d bytes\n", n4) - - w.Flush() - -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG307 - Poor permissions for os.Create - SampleCodeG307 = []CodeSample{ - {[]string{`package main - -import ( - "fmt" - "os" -) - -func check(e error) { - if e != nil { - panic(e) - } -} - -func main() { - f, err := os.Create("/tmp/dat2") - check(err) - defer f.Close() -}`}, 0, gosec.NewConfig()}, - {[]string{`package main - -import ( - "fmt" - "os" -) - -func check(e error) { - if e != nil { - panic(e) - } -} - -func main() { - f, err := os.Create("/tmp/dat2") - check(err) - defer f.Close() -}`}, 1, gosec.Config{"G307": "0o600"}}, - } - - // SampleCodeG401 - Use of weak crypto MD5 - SampleCodeG401 = []CodeSample{ - {[]string{` -package main - -import ( - "crypto/md5" - "fmt" - "io" - "log" - "os" -) - -func main() { - f, err := os.Open("file.txt") - if err != nil { - log.Fatal(err) - } - defer f.Close() - - defer func() { - err := f.Close() - if err != nil { - log.Printf("error closing the file: %s", err) - } - }() - - h := md5.New() - if _, err := io.Copy(h, f); err != nil { - log.Fatal(err) - } - fmt.Printf("%x", h.Sum(nil)) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG401b - Use of weak crypto SHA1 - SampleCodeG401b = []CodeSample{ - {[]string{` -package main - -import ( - "crypto/sha1" - "fmt" - "io" - "log" - "os" -) -func main() { - f, err := os.Open("file.txt") - if err != nil { - log.Fatal(err) - } - defer f.Close() - - h := sha1.New() - if _, err := io.Copy(h, f); err != nil { - log.Fatal(err) - } - fmt.Printf("%x", h.Sum(nil)) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG402 - TLS settings - SampleCodeG402 = []CodeSample{ - {[]string{` -// InsecureSkipVerify -package main - -import ( - "crypto/tls" - "fmt" - "net/http" -) - -func main() { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - - client := &http.Client{Transport: tr} - _, err := client.Get("https://golang.org/") - if err != nil { - fmt.Println(err) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -// InsecureSkipVerify from variable -package main - -import ( - "crypto/tls" -) - -func main() { - var conf tls.Config - conf.InsecureSkipVerify = true -}`}, 1, gosec.NewConfig()}, - {[]string{ - ` -// Insecure minimum version -package main - -import ( - "crypto/tls" - "fmt" - "net/http" -) - -func main() { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{MinVersion: 0}, - } - client := &http.Client{Transport: tr} - _, err := client.Get("https://golang.org/") - if err != nil { - fmt.Println(err) - } -}`, - }, 1, gosec.NewConfig()}, - {[]string{ - ` -// Insecure minimum version -package main - -import ( - "crypto/tls" - "fmt" -) - -func CaseNotError() *tls.Config { - var v uint16 = tls.VersionTLS13 - - return &tls.Config{ - MinVersion: v, - } -} - -func main() { - a := CaseNotError() - fmt.Printf("Debug: %v\n", a.MinVersion) -}`, - }, 0, gosec.NewConfig()}, - {[]string{ - ` -// Insecure minimum version -package main - -import ( - "crypto/tls" - "fmt" -) - -func CaseNotError() *tls.Config { - return &tls.Config{ - MinVersion: tls.VersionTLS13, - } -} - -func main() { - a := CaseNotError() - fmt.Printf("Debug: %v\n", a.MinVersion) -}`, - }, 0, gosec.NewConfig()}, - {[]string{ - ` -// Insecure minimum version -package main -import ( - "crypto/tls" - "fmt" -) - -func CaseError() *tls.Config { - var v = &tls.Config{ - MinVersion: 0, - } - return v -} - -func main() { - a := CaseError() - fmt.Printf("Debug: %v\n", a.MinVersion) -}`, - }, 1, gosec.NewConfig()}, - {[]string{ - ` -// Insecure minimum version -package main - -import ( - "crypto/tls" - "fmt" -) - -func CaseError() *tls.Config { - var v = &tls.Config{ - MinVersion: getVersion(), - } - return v -} - -func getVersion() uint16 { - return tls.VersionTLS12 -} - -func main() { - a := CaseError() - fmt.Printf("Debug: %v\n", a.MinVersion) -}`, - }, 1, gosec.NewConfig()}, - {[]string{ - ` -// Insecure minimum version -package main - -import ( - "crypto/tls" - "fmt" - "net/http" -) - -var theValue uint16 = 0x0304 - -func main() { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{MinVersion: theValue}, - } - client := &http.Client{Transport: tr} - _, err := client.Get("https://golang.org/") - if err != nil { - fmt.Println(err) - } -} -`, - }, 0, gosec.NewConfig()}, - {[]string{` -// Insecure max version -package main - -import ( - "crypto/tls" - "fmt" - "net/http" -) - -func main() { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{MaxVersion: 0}, - } - client := &http.Client{Transport: tr} - _, err := client.Get("https://golang.org/") - if err != nil { - fmt.Println(err) - } -} -`}, 1, gosec.NewConfig()}, - { - []string{` -// Insecure ciphersuite selection -package main - -import ( - "crypto/tls" - "fmt" - "net/http" -) - -func main() { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{CipherSuites: []uint16{ - tls.TLS_RSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - },}, - } - client := &http.Client{Transport: tr} - _, err := client.Get("https://golang.org/") - if err != nil { - fmt.Println(err) - } -}`}, 1, gosec.NewConfig(), - }, - {[]string{` -// secure max version when min version is specified -package main - -import ( - "crypto/tls" - "fmt" - "net/http" -) - -func main() { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{MaxVersion: 0, MinVersion: tls.VersionTLS13}, - } - client := &http.Client{Transport: tr} - _, err := client.Get("https://golang.org/") - if err != nil { - fmt.Println(err) - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package p0 - -import "crypto/tls" - -func TlsConfig0() *tls.Config { - var v uint16 = 0 - return &tls.Config{MinVersion: v} -} -`, ` -package p0 - -import "crypto/tls" - -func TlsConfig1() *tls.Config { - return &tls.Config{MinVersion: 0x0304} -} -`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "crypto/tls" - "fmt" -) - -func main() { - cfg := tls.Config{ - MinVersion: MinVer, - } - fmt.Println("tls min version", cfg.MinVersion) -} -`, ` -package main - -import "crypto/tls" - -const MinVer = tls.VersionTLS13 -`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "crypto/tls" - cryptotls "crypto/tls" -) - -func main() { - _ = tls.Config{MinVersion: tls.VersionTLS12} - _ = cryptotls.Config{MinVersion: cryptotls.VersionTLS12} -} -`}, 0, gosec.NewConfig()}, - } - - // SampleCodeG403 - weak key strength - SampleCodeG403 = []CodeSample{ - {[]string{` -package main - -import ( - "crypto/rand" - "crypto/rsa" - "fmt" -) - -func main() { - //Generate Private Key - pvk, err := rsa.GenerateKey(rand.Reader, 1024) - if err != nil { - fmt.Println(err) - } - fmt.Println(pvk) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG404 - weak random number - SampleCodeG404 = []CodeSample{ - {[]string{` -package main - -import "crypto/rand" - -func main() { - good, _ := rand.Read(nil) - println(good) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "math/rand" - -func main() { - bad := rand.Int() - println(bad) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "crypto/rand" - mrand "math/rand" -) - -func main() { - good, _ := rand.Read(nil) - println(good) - bad := mrand.Int31() - println(bad) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "math/rand" -) - -func main() { - gen := rand.New(rand.NewSource(10)) - bad := gen.Int() - println(bad) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "math/rand" -) - -func main() { - bad := rand.Intn(10) - println(bad) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "crypto/rand" - "math/big" - rnd "math/rand" -) - -func main() { - good, _ := rand.Int(rand.Reader, big.NewInt(int64(2))) - println(good) - bad := rnd.Intn(2) - println(bad) -} -`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - crand "crypto/rand" - "math/big" - "math/rand" - rand2 "math/rand" - rand3 "math/rand" -) - -func main() { - _, _ = crand.Int(crand.Reader, big.NewInt(int64(2))) // good - - _ = rand.Intn(2) // bad - _ = rand2.Intn(2) // bad - _ = rand3.Intn(2) // bad -} -`}, 3, gosec.NewConfig()}, - } - - // SampleCodeG501 - Blocklisted import MD5 - SampleCodeG501 = []CodeSample{ - {[]string{` -package main - -import ( - "crypto/md5" - "fmt" - "os" -) - -func main() { - for _, arg := range os.Args { - fmt.Printf("%x - %s\n", md5.Sum([]byte(arg)), arg) - } -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG502 - Blocklisted import DES - SampleCodeG502 = []CodeSample{ - {[]string{` -package main - -import ( - "crypto/cipher" - "crypto/des" - "crypto/rand" - "encoding/hex" - "fmt" - "io" -) - -func main() { - block, err := des.NewCipher([]byte("sekritz")) - if err != nil { - panic(err) - } - plaintext := []byte("I CAN HAZ SEKRIT MSG PLZ") - ciphertext := make([]byte, des.BlockSize+len(plaintext)) - iv := ciphertext[:des.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - panic(err) - } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[des.BlockSize:], plaintext) - fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext)) -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG503 - Blocklisted import RC4 - SampleCodeG503 = []CodeSample{{[]string{` -package main - -import ( - "crypto/rc4" - "encoding/hex" - "fmt" -) - -func main() { - cipher, err := rc4.NewCipher([]byte("sekritz")) - if err != nil { - panic(err) - } - plaintext := []byte("I CAN HAZ SEKRIT MSG PLZ") - ciphertext := make([]byte, len(plaintext)) - cipher.XORKeyStream(ciphertext, plaintext) - fmt.Println("Secret message is: %s", hex.EncodeToString(ciphertext)) -}`}, 1, gosec.NewConfig()}} - - // SampleCodeG504 - Blocklisted import CGI - SampleCodeG504 = []CodeSample{{[]string{` -package main - -import ( - "net/http/cgi" - "net/http" - ) - -func main() { - cgi.Serve(http.FileServer(http.Dir("/usr/share/doc"))) -}`}, 1, gosec.NewConfig()}} - // SampleCodeG505 - Blocklisted import SHA1 - SampleCodeG505 = []CodeSample{ - {[]string{` -package main - -import ( - "crypto/sha1" - "fmt" - "os" -) - -func main() { - for _, arg := range os.Args { - fmt.Printf("%x - %s\n", sha1.Sum([]byte(arg)), arg) - } -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeG601 - Implicit aliasing over range statement - SampleCodeG601 = []CodeSample{ - {[]string{ - ` -package main - -import "fmt" - -var vector []*string -func appendVector(s *string) { - vector = append(vector, s) -} - -func printVector() { - for _, item := range vector { - fmt.Printf("%s", *item) - } - fmt.Println() -} - -func foo() (int, **string, *string) { - for _, item := range vector { - return 0, &item, item - } - return 0, nil, nil -} - -func main() { - for _, item := range []string{"A", "B", "C"} { - appendVector(&item) - } - - printVector() - - zero, c_star, c := foo() - fmt.Printf("%d %v %s", zero, c_star, c) -}`, - }, 1, gosec.NewConfig()}, - {[]string{` -// see: github.com/securego/gosec/issues/475 -package main - -import ( - "fmt" -) - -func main() { - sampleMap := map[string]string{} - sampleString := "A string" - for sampleString, _ = range sampleMap { - fmt.Println(sampleString) - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -type sampleStruct struct { - name string -} - -func main() { - samples := []sampleStruct{ - {name: "a"}, - {name: "b"}, - } - for _, sample := range samples { - fmt.Println(sample.name) - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -type sampleStruct struct { - name string -} - -func main() { - samples := []*sampleStruct{ - {name: "a"}, - {name: "b"}, - } - for _, sample := range samples { - fmt.Println(&sample) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -type sampleStruct struct { - name string -} - -func main() { - samples := []*sampleStruct{ - {name: "a"}, - {name: "b"}, - } - for _, sample := range samples { - fmt.Println(&sample.name) - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -type sampleStruct struct { - name string -} - -func main() { - samples := []sampleStruct{ - {name: "a"}, - {name: "b"}, - } - for _, sample := range samples { - fmt.Println(&sample.name) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -type subStruct struct { - name string -} - -type sampleStruct struct { - sub subStruct -} - -func main() { - samples := []sampleStruct{ - {sub: subStruct{name: "a"}}, - {sub: subStruct{name: "b"}}, - } - for _, sample := range samples { - fmt.Println(&sample.sub.name) - } -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -type subStruct struct { - name string -} - -type sampleStruct struct { - sub subStruct -} - -func main() { - samples := []*sampleStruct{ - {sub: subStruct{name: "a"}}, - {sub: subStruct{name: "b"}}, - } - for _, sample := range samples { - fmt.Println(&sample.sub.name) - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import ( - "fmt" -) - -func main() { - one, two := 1, 2 - samples := []*int{&one, &two} - for _, sample := range samples { - fmt.Println(&sample) - } -}`}, 1, gosec.NewConfig()}, - } - - // SampleCodeBuildTag - G601 build tags - SampleCodeBuildTag = []CodeSample{{[]string{` -// +build tag -package main - -func main() { - fmt.Println("no package imported error") -}`}, 1, gosec.NewConfig()}} - - // SampleCodeCgo - Cgo file sample - SampleCodeCgo = []CodeSample{{[]string{` -package main - -import ( - "fmt" - "unsafe" -) - -/* -#include -#include -#include - -int printData(unsigned char *data) { - return printf("cData: %lu \"%s\"\n", (long unsigned int)strlen(data), data); -} -*/ -import "C" - -func main() { - // Allocate C data buffer. - width, height := 8, 2 - lenData := width * height - // add string terminating null byte - cData := (*C.uchar)(C.calloc(C.size_t(lenData+1), C.sizeof_uchar)) - - // When no longer in use, free C allocations. - defer C.free(unsafe.Pointer(cData)) - - // Go slice reference to C data buffer, - // minus string terminating null byte - gData := (*[1 << 30]byte)(unsafe.Pointer(cData))[:lenData:lenData] - - // Write and read cData via gData. - for i := range gData { - gData[i] = '.' - } - copy(gData[0:], "Data") - gData[len(gData)-1] = 'X' - fmt.Printf("gData: %d %q\n", len(gData), gData) - C.printData(cData) -} -`}, 0, gosec.NewConfig()}} - - // SampleCodeG602 - Slice access out of bounds - SampleCodeG602 = []CodeSample{ - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 0) - - fmt.Println(s[:3]) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 0) - - fmt.Println(s[3:]) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 16) - - fmt.Println(s[:17]) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 16) - - fmt.Println(s[:16]) - -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 16) - - fmt.Println(s[5:17]) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 4) - - fmt.Println(s[3]) - -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 4) - - fmt.Println(s[5]) - -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 0) - s = make([]byte, 3) - - fmt.Println(s[:3]) - -}`}, 0, gosec.NewConfig()}, - - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 0, 4) - - fmt.Println(s[:3]) - fmt.Println(s[3]) - -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - - s := make([]byte, 0, 4) - - fmt.Println(s[:5]) - fmt.Println(s[7]) - -}`}, 2, gosec.NewConfig()}, - {[]string{` - package main - - import "fmt" - - func main() { - - s := make([]byte, 0, 4) - x := s[:2] - y := x[:10] - fmt.Println(y) - }`}, 1, gosec.NewConfig()}, - - {[]string{` - package main - - import "fmt" - - func main() { - - s := make([]int, 0, 4) - doStuff(s) - } - - func doStuff(x []int) { - newSlice := x[:10] - fmt.Println(newSlice) - }`}, 1, gosec.NewConfig()}, - {[]string{` - package main - - import "fmt" - - func main() { - - s := make([]int, 0, 30) - doStuff(s) - x := make([]int, 20) - y := x[10:] - doStuff(y) - z := y[5:] - doStuff(z) - } - - func doStuff(x []int) { - newSlice := x[:10] - fmt.Println(newSlice) - newSlice2 := x[:6] - fmt.Println(newSlice2) - }`}, 2, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - testMap := make(map[string]any, 0) - testMap["test1"] = map[string]interface{}{ - "test2": map[string]interface{}{ - "value": 0, - }, - } - fmt.Println(testMap) -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - s := make([]byte, 0) - if len(s) > 0 { - fmt.Println(s[0]) - } -}`}, 0, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - s := make([]byte, 0) - if len(s) > 0 { - fmt.Println("fake test") - } - fmt.Println(s[0]) -}`}, 1, gosec.NewConfig()}, - {[]string{` -package main - -import "fmt" - -func main() { - s := make([]int, 16) - for i := 0; i < 17; i++ { - s = append(s, i) - } - if len(s) < 16 { - fmt.Println(s[10:16]) - } else { - fmt.Println(s[3:18]) - } - fmt.Println(s[0]) - for i := range s { - fmt.Println(s[i]) - } -}`}, 0, gosec.NewConfig()}, - } -)