Rule | Description | Example | KPI | |
---|---|---|---|---|
G107-UrlProvidedToHTTPRequestAsTaintInput | Getting a URL from an untrusted source like user input, gives the ability of an attacker to redirect your application to bad websites and perform additional attacks. One of the examples is the http.Get() function issues a GET to the specified URL and if the result is appropriate GET will follow the redirect after calling Client's CheckRedirect function. That means that the attacker can send your application to various places.This problem leads to SSRF attacks via http requests with variable url. | //non-compliant code package main import ( "fmt" "io/ioutil" "net/http" ) var url string = "http://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) } //compliant code package main import ( "fmt" "net/http" ) const url = "https://127.0.0.1" func main() { resp, err := http.Get(url) if err != nil { fmt.Println(err) } fmt.Println(resp.Status) } | Security | - [Source](https://github.com/securego/gosec#available-rules) - [CWE-88](https://cwe.mitre.org/data/definitions/88.html) - Improper Neutralization of Argument Delimiters in a Command ('Argument Injection') - [OWASP Top 10 2013 Category A10](https://blog.detectify.com/2016/08/15/owasp-top-10-unvalidated-redirects-and-forwards-10/) - Unvalidated Redirects and Forwards |
G109-PotentialIntegerOverflowMadeByStrconv-Atoiresultconversiontoint16-32 | Potential Integer overflow made by strconv.Atoi result conversion to int16/32.The strconv.Atoi function parses an int - a machine dependent integer type, which, for 64-bit targets will be int64. There are places throughout the codebase where the result returned from strconv.Atoi is later converted to a smaller type: int16 or int32. This may overflow with a certain input. | //non-compliant code package main import ( "fmt" "strconv" ) func updatePodPorts(params map[string]string, podSpec *v1.PodSpec) (err error) { port := -1 hostPort := -1 if len(params["port"]) > 0 { port, err = strconv.Atoi(params["port"]) // <-- this should parse port as strconv.ParseUint(params["port"], 10, 16) if err != nil { return err } } // (...) // Don't include the port if it was not specified. if len(params["port"]) > 0 { podSpec.Containers[0].Ports = []v1.ContainerPort{ { ContainerPort: int32(port), // <-- this should later just be uint16(port) }, } } //compliant code package main import ( "fmt" "strconv" ) func updatePodPorts(params map[string]string, podSpec *v1.PodSpec) (err error) { port := -1 hostPort := -1 if len(params["port"]) > 0 { port, err = strconv.ParseUint(params["port"], 10, 16) if err != nil { return err } } // (...) // Don't include the port if it was not specified. if len(params["port"]) > 0 { podSpec.Containers[0].Ports = []v1.ContainerPort{ { ContainerPort: uint16(port), }, } } | Security | |
G201-SQLqueryconstructionusingformatstring | Do not use packages like "fmt" in technologies like SQL or HTML. SQL injection is one of the top security issues developers make and the consequences of this can be severe. Using the format string function in the fmt Golang package to dynamically create an SQL query can easily create a possibility for SQL injection. The reason is that the format string function doesn't escape special characters like ' and it's easy to add second SQL command in the format string. | /non-compliant code 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() } //compliant code 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() } | Security | |
G202-SQLQueryConstructionuSingStringConcatenation | Do not construct SQL queries using string concatenation.Instead use the database/sql. By using the database/sql package along with argument placeholders, you are able to construct SQL statements that are automatically escaped properly. There is no need to construct the SQL statement manually, but instead provide arguments that can be easily escaped. The underlying driver for database/sql will be aware of special characters which needs to be handled and will escape them, preventing any nefarious SQL from running. | //non-compliant code 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) } var gender string = "M" rows, err := db.Query("SELECT * FROM foo WHERE gender = " + gender) if err != nil { panic(err) } defer rows.Close() } //compliant code package main import ( "database/sql" "bufio" ) func main(){ db, err := sql.Open("sqlite3", ":memory:") if err != nil { panic(err) } in := bufio.NewReader(os.Stdin) name, err := in.ReadString('\n') if err != nil { panic(err) } rows, err := db.Query("SELECT * FROM foo WHERE name = ?", name) if err != nil { panic(err) } defer rows.Close() } | Security | - [Source](https://github.com/securego/gosec#available-rules) - [CWE-89](https://cwe.mitre.org/data/definitions/89.html) - Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') |
G204-AuditUseOfCommandExecution | Audit use of command execution. Go-audit is an alternative to auditd with better logging. It exports logs in JSON and combines multiple events, with same root cause, into one event for easy analysis. | //non-compliant code for _, files := range protoFilesMap { for _, relProtoFile := range files { args := []string{ "--go_out", pwd, } args = append(args, relProtoFile) cmd := exec.Command(protoc, args...) cmd.Env = append(cmd.Env, os.Environ()...) } | Security | |
G301-PoorFilePermissionsUsedWhenCreatingADirectory | Do not use poor file permissions when creating a directory. Directory permission should be 0750 or less while creating a it. | //non-compliant code package main import ( "log" "os" ) func main() { _, err := os.Stat("test") if os.IsNotExist(err) { errDir := os.MkdirAll("test", 0755) if errDir != nil { log.Fatal(err) } } } //compliant code package main import ( "log" "os" ) func main() { _, err := os.Stat("test") if os.IsNotExist(err) { errDir := os.MkdirAll("test", 0750) if errDir != nil { log.Fatal(err) } } } | Security | - [CWE-276](https://cwe.mitre.org/data/definitions/276.html) - Incorrect Default Permissions |
G302-PoorFilePermissionsUsedWithchmod | Do not use poor file permissions for a file with chmod. Use file permimssion 0600 or less. | //non-compliant code package main import ( "log" "os" "time" ) func main() { // Test File existence. _, err := os.Stat("test.txt") if err != nil { if os.IsNotExist(err) { log.Fatal("File does not exist.") } } log.Println("File exist.") // Change permissions Linux. err = os.Chmod("test.txt", 0777) if err != nil { log.Println(err) } //compliant code package main import ( "log" "os" "time" ) func main() { // Test File existence. _, err := os.Stat("test.txt") if err != nil { if os.IsNotExist(err) { log.Fatal("File does not exist.") } } log.Println("File exist.") // Change permissions Linux. err = os.Chmod("test.txt", 0600) if err != nil { log.Println(err) } | Security | - [CWE-276](https://cwe.mitre.org/data/definitions/276.html) - Incorrect Default Permissions |
G303-CreatingTempFileUsingaPredictablePath | Creating tempfile using a predictable path | Security | ||
G304-FilePathprovidedastaintinput | File path provided as taint input | //non-compliant code package main import ( "os" "fmt" "path/filepath" ) func (v upgradeCommand) verifyChecksum(source, checksum string) error { var ( err error h hash.Hash ) checksumFile, err := os.Open(checksum) if err != nil { return err } } | Security | - [CWE-22](https://cwe.mitre.org/data/definitions/22.html) - Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') |
G306-PoorFilePermissionsUsedWhenWritingToANewFile | DO not use Poor file permissions when writing to a new file. Expected permission is 0600 or less for writing in a new file. | //non compliant code package main import ( "fmt" "io/ioutil" "os" "path/filepath" ) func main() { dname, err := ioutil.TempDir("", "sampledir") check(err) fmt.Println("Temp dir name:", dname) defer os.RemoveAll(dname) fname := filepath.Join(dname, "file1") err = ioutil.WriteFile(fname, []byte{1, 2}, 0777) check(err) } //compliant code package main import ( "fmt" "io/ioutil" "os" "path/filepath" ) func main() { dname, err := ioutil.TempDir("", "sampledir") check(err) fmt.Println("Temp dir name:", dname) defer os.RemoveAll(dname) fname := filepath.Join(dname, "file1") err = ioutil.WriteFile(fname, []byte{1, 2}, 0600) check(err) } | Security | - [CWE-276](https://cwe.mitre.org/data/definitions/276.html) - Incorrect Default Permissions |
G307-DeferringaMethodWhichReturnsAnError | Deferring a method which returns an error | //non-compliant code package main import ( "os" "fmt" ) func main() { checksumFile, err := os.Open(checksum) if err != nil { return err } defer checksumFile.Close() } | Security | |
G403-EnsureMinimumRSAkeyLengthOf2048Bits | Ensure minimum RSA key length of 2048 bits. RSA encryption is more computationally expensive than typical symmetric ciphers such as AES. The key generation and decryption operations in particular are relatively expensive operations. Guidelines on RSA key length : 1) For relatively low level of security and running modest hardware, choose an RSA key length of at least 2048 bits. 2) For dedicated hardware and/or achieve good security, consider a key size of 4096 bits. 3) If long-term high security is required, ensure that system could be reconfigured at a later date to use a higher key length. | //non-compliant code package main import ( "crypto/rand" "crypto/rsa" "fmt" "os" ) func main() { // generate key privatekey, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { fmt.Printf("Cannot generate RSA key\n") os.Exit(1) } } //compliant code package main import ( "crypto/rand" "crypto/rsa" "fmt" "os" ) func main() { // generate key privatekey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { fmt.Printf("Cannot generate RSA key\n") os.Exit(1) } } | Security | - [CWE-310](https://cwe.mitre.org/data/definitions/310.html) - Cryptographic Issues |
G601-ImplicitMemoryAliasingOfItemsFromARangeStatement | Implicit memory aliasing of items from a range statement | //non-compliant code package main func main() { var a [5]int for i, k := range a { fmt.Println(&k) // non compliant } } //compliant code package main func main() { var a [5]int for i, k := range a { fmt.Println(&a[i]) // non compliant } } | Security |