Science and technology

Find safety points in Go code utilizing gosec

It’s extraordinarily frequent now to come across code written within the Go programming language, particularly in case you are working with containers, Kubernetes, or a cloud ecosystem. Docker was one of many first tasks to undertake Golang, Kubernetes adopted, and plenty of new tasks choose Go over different programming languages.

Like every other language, Go has its share of strengths and weaknesses, which embrace safety flaws. These can come up as a result of points within the programming language itself coupled with insecure coding practices, similar to reminiscence issues of safety in C code, for instance.

Regardless of why they happen, safety points must be fastened early in improvement to forestall them from creeping into shipped software program. Fortunately, static evaluation instruments can be found that can assist you deal with these points in a extra repeatable method. Static evaluation instruments work by parsing supply code written in a programming language and searching for points.

Many of those instruments are known as linters. Traditionally, linters are extra centered on discovering programming points, bugs, code fashion points, and the like, they usually might not discover safety points in code. For instance, Coverity is a well-liked device that helps discover points in C/C++ code. However, there are instruments that particularly hunt down safety points in supply code. For instance, Bandit seems for safety flaws in Python code. And gosec searches for safety flaws in Go supply code. Gosec scans the Go summary syntax tree (AST) to examine supply code for safety issues.

Get began with gosec

To mess around with gosec and be taught the way it works, you want a undertaking written in Go. With all kinds of open supply software program accessible, this should not be an issue. You can discover one by wanting on the trending Golang repositorties on GitHub.

For this tutorial, I randomly selected the Docker CE undertaking, however you may select any Go undertaking you need.

Install Go and gosec

If you don’t have already got Go put in, you may fetch it out of your repository. If you employ Fedora or one other RPM-based Linux distribution:

$ dnf set up golang.x86_64

Or you may go to the Golang install web page for different choices on your working system.

Verify that Go is put in in your system utilizing the model argument:

$ go model
go model go1.14.6 linux/amd64
$

Installing gosec is just a matter of operating the go get command:

$ go get github.com/securego/gosec/cmd/gosec
$

This downloads gosec’s supply code from GitHub, compiles it, and installs it in a particular location. You can discover other ways of installing the tools within the repo’s README.

Gosec’s supply code must be downloaded to the situation set by $GOPATH, and the compiled binary might be put in within the bin listing you set on your system. To discover out what $GOPATH and $GOBIN level to, run:

$ go env | grep GOBIN
GOBIN="/root/go/gobin"
$
$ go env | grep GOPATH
GOPATH="/root/go"
$

If the go get command labored, then the gosec binary must be accessible:

$
$ ls -l ~/go/bin/
whole 9260
-rwxr-xr-x. 1 root root 9482175 Aug 20 04:17 gosec
$

You can add the bin listing in $GOPATH to the $PATH variable in your shell. This makes the gosec command-line interface (CLI) accessible similar to every other command line in your system:

$ which gosec
/root/go/bin/gosec
$

Try operating the gosec CLI with the -help choice to see whether it is working as anticipated:

$ gosec -help

gosec - Golang safety checker

gosec analyzes Go supply code to look for frequent programming errors that
can result in safety issues.

VERSION: dev
GIT TAG:
BUILD DATE:

USAGE:

Next, create a listing and get the supply code for the demo undertaking (Docker CE, on this case) utilizing:

$ mkdir gosec-demo
$
$ cd gosec-demo/
$
$ pwd
/root/gosec-demo
$

$ git clone https://github.com/docker/docker-ce.git
Cloning into 'docker-ce'...
distant: Enumerating objects: 1271, accomplished.
distant: Counting objects: 100% (1271/1271), accomplished.
distant: Compressing objects: 100% (722/722), accomplished.
distant: Total 431003 (delta 384), reused 981 (delta 318), pack-reused 429732
Receiving objects: 100% (431003/431003), 166.84 MiB | 28.94 MiB/s, accomplished.
Resolving deltas: 100% (221338/221338), accomplished.
Updating information: 100% (10861/10861), accomplished.
$

A fast have a look at the supply code reveals that many of the undertaking is written in Go—simply what you’ll want to tinker with gosec’s options:

$ ./cloc /root/gosec-demo/docker-ce/
   10771 textual content information.
    8724 distinctive information.                                          
    2560 information ignored.

-----------------------------------------------------------------------------------
Language                         information          clean        remark           code
-----------------------------------------------------------------------------------
Go                                7222         190785         230478        1574580
YAML                                37           4831            817         156762
Markdown                           529          21422              zero          67893
Protocol Buffers                   149           5014          16562          10071

Run gosec with the default choices

Run gosec on the Docker CE undertaking utilizing the default choices by operating gosec ./... from inside the Git repo you simply cloned. Lots of output might be proven on the display screen. Towards the tip, you must see a brief Summary exhibiting the variety of information scanned, the variety of strains in these information, and the problems it discovered within the supply code:

$ pwd
/root/gosec-demo/docker-ce
$
$ time gosec ./...
[gosec] 2020/08/20 04:44:15 Including guidelines: default
[gosec] 2020/08/20 04:44:15 Excluding guidelines: default
[gosec] 2020/08/20 04:44:15 Import listing: /root/gosec-demo/docker-ce/parts/engine/opts
[gosec] 2020/08/20 04:44:17 Checking bundle: opts
[gosec] 2020/08/20 04:44:17 Checking file: /root/gosec-demo/docker-ce/parts/engine/opts/address_pools.go
[gosec] 2020/08/20 04:44:17 Checking file: /root/gosec-demo/docker-ce/parts/engine/opts/env.go
[gosec] 2020/08/20 04:44:17 Checking file: /root/gosec-demo/docker-ce/parts/engine/opts/hosts.go

# End of gosec run

Summary:
   Files: 1278
   Lines: 173979
   Nosec: four
  Issues: 644

actual    0m52.019s
consumer    0m37.284s
sys     0m12.734s
$

If you scroll via the output on the display screen, you must see some strains highlighted in varied colours: purple signifies high-priority points that must be seemed into first, and yellow signifies medium-priority points.

About false positives

Before entering into the findings, I wish to share some floor guidelines. By default, static evaluation instruments report every part that they discover to be a problem based mostly on a algorithm that the device compares towards the code being examined. Does this imply that every part reported by the device is a matter that must be fastened? Well, it relies upon. The greatest authorities on this query are the builders who designed and developed the software program. They perceive the code a lot better than anyone else, and extra importantly, they perceive the atmosphere the place the software program might be deployed and the way will probably be used.

This information is crucial when deciding whether or not a chunk of code flagged by a device is definitely a safety flaw. Over time and with extra expertise, you’ll be taught to tweak static evaluation instruments to disregard points that aren’t safety flaws and make the stories extra actionable. So, an skilled developer doing a guide audit of the supply code can be in a greater place to resolve whether or not a problem reported by gosec warrants consideration or not.

High-priority points

According to the output, gosec discovered a high-priority difficulty that Docker CE is utilizing an previous Transport Layer Security (TLS) model. Whenever attainable, it is best to make use of the newest model of a software program or library to make sure it’s updated and has no safety points.

[/root/gosec-demo/docker-ce/parts/engine/daemon/logger/splunk/splunk.go:173] - G402 (CWE-295): TLS MinVersion too low. (Confidence: HIGH, Severity: HIGH)
    172:
  > 173:        tlsConfig := &tls.Config
    174:

It additionally discovered a weak random quantity generator. Depending on how the generated random quantity is used, you may resolve whether or not or not this can be a safety flaw.

[/root/gosec-demo/docker-ce/parts/engine/pkg/namesgenerator/names-generator.go:843] - G404 (CWE-338): Use of weak random quantity generator (math/rand as an alternative of crypto/rand) (Confidence: MEDIUM, Severity: HIGH)
    842: start:
  > 843:        identify := fmt.Sprintf("%s_%s", left[rand.Intn(len(left))], proper[rand.Intn(len(proper))])
    844:        if identify == "boring_wozniak" /* Steve Wozniak will not be boring */ {

Medium-priority points

The device additionally discovered some medium-priority points. It flagged a possible denial of service (DoS) vulnerability by the use of a decompression bomb associated to a tar that would probably be exploited by a malicious actor.

[/root/gosec-demo/docker-ce/parts/engine/pkg/archive/copy.go:357] - G110 (CWE-409): Potential DoS vulnerability through decompression bomb (Confidence: MEDIUM, Severity: MEDIUM)
    356:
  > 357:                        if _, err = io.Copy(rebasedTar, srcTar); err != nil {
    358:                                w.CloseWithError(err)

It additionally discovered a problem associated to a file that’s included by the use of a variable. If malicious customers take management of this variable, they might change its contents to learn a special file.

[/root/gosec-demo/docker-ce/parts/cli/cli/context/tlsdata.go:80] - G304 (CWE-22): Potential file inclusion through variable (Confidence: HIGH, Severity: MEDIUM)
    79:         if caPath != "" {
  > 80:                 if ca, err = ioutil.LearnFile(caPath); err != nil {
    81:                         return nil, err

File and listing permissions are sometimes the essential constructing blocks of safety on an working system. Here, gosec recognized a problem the place you would possibly have to test whether or not the permissions for a listing are safe or not.

[/root/gosec-demo/docker-ce/parts/engine/contrib/apparmor/primary.go:41] - G301 (CWE-276): Expect listing permissions to be 0750 or much less (Confidence: HIGH, Severity: MEDIUM)
    40:         // make certain /and so forth/apparmor.d exists
  > 41:         if err := os.MkdirAll(path.Dir(apparmorProfilePath), 0755); err != nil {
    42:                 log.Fatal(err)

Often, you’ll want to launch command-line utilities from supply code. Go makes use of the built-in exec library to do that job. Carefully analyzing the variable used to spawn such utilities can uncover safety flaws.

[/root/gosec-demo/docker-ce/parts/engine/testutil/fakestorage/fixtures.go:59] - G204 (CWE-78): Subprocess launched with variable (Confidence: HIGH, Severity: MEDIUM)
    58:
  > 59:              cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
    60:                 cmd.Env = append(os.Environ(), []string{

Low-severity points

In this output, gosec recognized low-severity points associated to “unsafe” calls, which usually bypass all of the reminiscence protections that Go supplies. Closely analyze your use of “unsafe” calls to see if they are often exploited in any manner attainable.

[/root/gosec-demo/docker-ce/parts/engine/pkg/archive/changes_linux.go:264] - G103 (CWE-242): Use of unsafe calls must be audited (Confidence: HIGH, Severity: LOW)
    263:        for len(buf) > zero {
  > 264:                dirent := (*unix.Dirent)(unsafe.Pointer(&buf[zero]))
    265:                buf = buf[dirent.Reclen:]

[/root/gosec-demo/docker-ce/parts/engine/pkg/devicemapper/devmapper_wrapper.go:88] - G103 (CWE-242): Use of unsafe calls must be audited (Confidence: HIGH, Severity: LOW)
    87: func free(p *C.char)
  > 88:         C.free(unsafe.Pointer(p))
    89:

It additionally flagged unhandled errors within the supply codebase. You are anticipated to deal with circumstances the place errors may come up within the supply code.

[/root/gosec-demo/docker-ce/parts/cli/cli/command/picture/construct/context.go:172] - G104 (CWE-703): Errors unhandled. (Confidence: HIGH, Severity: LOW)
    171:                err := tar.Close()
  > 172:                os.RemoveAll(dockerfileDir)
    173:                return err

Customize gosec scans

Using gosec with its defaults brings up many sorts of points. However, with guide auditing and over time, you be taught which points do not must be flagged. You can customise gosec to exclude or embrace sure exams.

As I discussed above, gosec makes use of a algorithm to seek out issues in Go supply code. Here is a whole listing of the rules it makes use of:

  • G101: Look for exhausting coded credentials
  • G102: Bind to all interfaces
  • G103: Audit using unsafe block
  • G104: Audit errors not checked
  • G106: Audit using ssh.InsecureIgnoreHostKey
  • G107: Url offered to HTTP request as taint enter
  • G108: Profiling endpoint routinely uncovered on /debug/pprof
  • G109: Potential Integer overflow made by strconv.Atoi outcome conversion to int16/32
  • G110: Potential DoS vulnerability through decompression bomb
  • G201: SQL question building utilizing format string
  • G202: SQL question building utilizing string concatenation
  • G203: Use of unescaped knowledge in HTML templates
  • G204: Audit use of command execution
  • G301: Poor file permissions used when making a listing
  • G302: Poor file permissions used with chmod
  • G303: Creating tempfile utilizing a predictable path
  • G304: File path offered as taint enter
  • G305: File traversal when extracting zip/tar archive
  • G306: Poor file permissions used when writing to a brand new file
  • G307: Deferring a way which returns an error
  • G401: Detect the utilization of DES, RC4, MD5 or SHA1
  • G402: Look for dangerous TLS connection settings
  • G403: Ensure minimal RSA key size of 2048 bits
  • G404: Insecure random quantity supply (rand)
  • G501: Import blocklist: crypto/md5
  • G502: Import blocklist: crypto/des
  • G503: Import blocklist: crypto/rc4
  • G504: Import blocklist: web/http/cgi
  • G505: Import blocklist: crypto/sha1
  • G601: Implicit reminiscence aliasing of things from a spread assertion

Exclude particular exams

You can customise gosec to forestall it from searching for and reporting on points which can be secure. To ignore particular points, you need to use the -exclude flag with the rule codes above.

For instance, if you don’t need gosec to seek out unhandled errors associated to hardcoding credentials in supply code, you may ignore them by operating:

$ gosec -exclude=G104 ./...
$ gosec -exclude=G104,G101 ./...

Sometimes, you understand an space of supply code is secure, however gosec retains reporting it as a problem. However, you do not wish to exclude that test fully since you need gosec to scan new code added to the codebase. To stop gosec from scanning the world you understand is secure, add a #nosec flag to that a part of the supply code. This ensures gosec continues to scan new code for a problem however ignores the world flagged with #nosec.

Run particular checks

On the opposite hand, if you’ll want to give attention to particular points, you need to use inform gosec to run these checks by utilizing the -include possibility with the rule codes:

$ gosec -include=G201,G202 ./...

Scan take a look at information

The Go language has built-in help for testing that makes use of unit exams to confirm whether or not a element works as anticipated. In default mode, gosec ignores take a look at information, however if you would like them included within the scan, use the -tests flag:

gosec -tests ./...

Change the output format

Finding points is simply a part of the image; the opposite half is reporting what it finds in a manner that’s simple for people and instruments to devour. Fortunately, gosec can output leads to a wide range of methods. For instance, if you wish to get stories in JSON format, use the -fmt choice to specify JSON and save the leads to a outcomes.json file:

$ gosec -fmt=json -out=outcomes.json ./...

$ ls -l outcomes.json
-rw-r--r--. 1 root root 748098 Aug 20 05:06 outcomes.json
$

         
             "severity": "LOW",
             "confidence": "HIGH",
             "cwe":
                 "ID": "242",
                 "URL": "https://cwe.mitre.org/data/definitions/242.html"
             ,
             "rule_id": "G103",
             "details": "Use of unsafe calls should be audited",
             "file": "/root/gosec-demo/docker-ce/components/engine/daemon/graphdriver/graphtest/graphtest_unix.go",
             "code": "304: t// Cast to []byten305: theader := *(*replicate.SliceHeader)(unsafe.Pointer(u0026buf))n306: theader.      Len *= eightn",
             "line": "305",
             "column": "36"
         ,

Find low-hanging fruit with gosec

A static evaluation device will not be a substitute for guide code audits. However, when a codebase is giant with many individuals contributing to it, such a device usually helps discover low-hanging fruit in a repeatable manner. It can also be helpful for serving to new builders determine and keep away from writing code that introduces these safety flaws.

Most Popular

To Top