Let’s Take a Look at the Rules of gas

  • Post author:
  • Post last modified:2020-11-25
  • Post category:Code Review
  • Reading time:9 mins read

There is a security testing tool for Golang called GAS(Go AST Scanner).
In this article, we’ll take a thorough look at the rules included in this tool.

The rules explained are as of January 5th, 2017.

Code Numbers

The rules in GAS have a code number, like “G101”.
These numbers have the following meaning:

  • G1xx : misc
  • G2xx : injection
  • G3xx : filesystem
  • G4xx : crypto
  • G5xx : blacklist

Now, let’s take a look at these rules one by one.

G101: Look for hardcoded credentials

Detects hardcoded credentials.


package samples
import “fmt”
func main() {
username := “admin”
password := “admin”
fmt.Println(“Doing something with: “, username, password)

A warning is issued when a value is assigned to a variable with the name passwd, pass, password, pwd, secret, or token.

It seems that these patterns can be altered in the configs (not checked). See https://github.com/GoASTScanner/gas/blob/d4f9b88cbf6b9f190a2425120c9cecc466ec363b/rules/hardcoded_credentials.go#L78-L80

G102: Bind to all interfaces

Detects codes making bindings to all network interfaces.


package main
import (
func main() {
l, err := net.Listen(“tcp”, “:2000”)
if err != nil {
defer l.Close()

net.Listen("tcp",”:2000")is equal to net.Listen("tcp",""). When implemented like this, access from all network interfaces become allowed.

This is dangerous since it allows access from other PCs connected to the same network. Especially, if you are using a public wireless LAN, anyone could access your application in development. 
This can be prevented by changing the code so it explicitly only allows access from localhost, like net.Listen("tcp",”")

If you’re a Rubyist, the changes to the Rack server may be a fresh memory.

G103: Audit the use of unsafe block

Detects function calls to unsafepackages.

G104: Audit errors not checked

Detects codes unchecked for errors.


os.Mkdir(“/foo”, 0700) // os.Mkdir returns an error, but this line does not check for it, resulting a warning
fmt.Println(“foo”) // Warnings are not made for functions that are generally not checked for errors, such as Println.

G201: SQL query construction using format string


q := fmt.Sprintf(“SELECT * FROM foo where name = ‘%s’”, name)

Note that this doesn’t regard whether the created string is actually used for SQL, so there is a false positive where gas warns you even if you use the qabove as like fmt.Println(q).

G202: SQL query construction using string concatenation

Detects codes creating SQL queries by concatenating strings.


q := “SELECT * FROM foo where name = ‘%s’” + name

It is very like the rule explained just now, and has a similar false positive.

G203: Use of unescaped data in HTML templates

Checks whether accepted external values are escaped when creating an HTML with a template.


t := template.Must(template.New(“ex”).Parse(tmpl))
v := map[string]interface{}{
“Title”: “Test <b>World</b>”, // No problems, since it is a literal
“Body”: template.HTML(a), // Causes a warning, because the external value will be used in the template without escaping
t.Execute(os.Stdout, v)

G204: Audit use of command execution



This check has 3 levels of ‘confidence’, being higher in the following order:

  • A non-literal value being used in a command or argument
  • The execution path of a command not being absolute
  • Others

G301: Poor file permissions used when creating a directory

Checks if the permissions for a created directory are excessive or not.


os.Mkdir(“/tmp/mydir”, 0777) // Warned, excessive permissions may be granted
os.Mkdir(“/tmp/mydir”, 0700) // No warning

At default, this check issues a warning when a permission greater than 0700 is granted.

G302: Poor file permisions used with chmod

A chmod/OpenFile version of G301. It is different from G301 where the default threshold for issuing a warning is 0600.

G303: Creating tempfile using a predictable path

Detects codes using os.Create when creating a temporary file.


file1, err := os.Create(“/tmp/demo1”)

When creating a temporary file, you should use ioutil.Tempfile instead of os.Create.

G401: Detect the usage of DES, RC4, or MD5

Detects codes using weak encryption algorithms.


// consider using algorithms such as SHA2, since md5 is vulnerable
// consider using algorithms such as AES, since DES is vulnurable

G402: Look for bad TLS connection settings

Detects codes with insecure TLS settings.

tr := &http.Transport{
// Verify skipped, resulting in a warning
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

There are some other detection items.

G403: Ensure minimum RSA key length of 2048 bits

Detects if an RSA key length is under 2048 bits.


pvk, err := rsa.GenerateKey(rand.Reader, 1024)

G404: Insecure random number source (rand)


import (
crand “crypto/rand”
mrand “math/rand”
crand.Rand(nil) // No warning, using crypto/rand
mrand.Rand(nil) // Warning, using math/rand

Since the official document for Golang states:

For random numbers suitable for security-sensitive work, see the crypto/rand package. https://golang.org/pkg/math/rand/

it would be sensible to use crypto/rand when needing to be secure with random numbers, such as using it for a session ID in a web application.

G501: Import blacklist: crypto/md5
G502: Import blacklist: crypto/des
G503: Import blacklist: crypto/rc4
G504: Import blacklist: net/http/cgi

Detects imports of these packages, since they are considered vulnerable.


import (
“crypto/md5” // you should use another algorithm such as SHA2 instead of MD5


That’s it for the rules in gas.
Why not ensure the security of your Go application with gas?

If there are any rules that cannot be adopted, you can disable specific rules with the -exclude option, like gas -exclude=G301,G104 main.go. Give it a try!

For more information about Sider, please go to our website.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.