RuleDescriptionExampleKPI
G107-UrlProvidedToHTTPRequestAsTaintInputGetting 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-32Potential 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-SQLqueryconstructionusingformatstringDo 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-SQLQueryConstructionuSingStringConcatenationDo 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-AuditUseOfCommandExecutionAudit 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-PoorFilePermissionsUsedWhenCreatingADirectoryDo 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-PoorFilePermissionsUsedWithchmodDo 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-CreatingTempFileUsingaPredictablePathCreating tempfile using a predictable pathSecurity
G304-FilePathprovidedastaintinputFile 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-PoorFilePermissionsUsedWhenWritingToANewFileDO 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-DeferringaMethodWhichReturnsAnErrorDeferring 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-EnsureMinimumRSAkeyLengthOf2048BitsEnsure 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-ImplicitMemoryAliasingOfItemsFromARangeStatementImplicit 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