Golang at Pendo
From Pendo’s inception, we have felt strongly about using performant, modern tools and languages to build our product with. Go was a conscious choice because it was built on 3 principles that were crucial to Pendo’s success and agility: efficient compilation, efficient execution, and ease of programming. A future blog post will discuss in detail the process of choosing Go, and all considerations that went into the decision-making process. If you would like to know more about Go, click here for a comprehensive FAQ.
SAST tools are slow to adopt Golang
As Go is a relatively new programming language (around 11 years old at the time this blog post was written), there are fewer static analysis tools available than for other, more widely used programming languages. We already had static analysis tools that provided us with comprehensive coverage for our front end resources, but to ensure our back end was also sufficiently covered, we needed to find a highly portable solution.
Why we chose Gosec
Gosec is an open source, static analysis tool. There were several reasons we chose gosec.
- It is written in Go – our favorite back end programming language
- As a result of it being written in Go, and being open source, it allows us to customize or even contribute in the future as needed
- It would be relatively easy to incorporate gosec into our CI/CD pipeline
The process of implementing gosec ended up being straightforward. The first step was to run gosec locally against one of our repositories with Go code without excluding any of the rules that come standard to gosec.
Below is a list of the rules that come standard with gosec:
We collected the results, and analyzed any issues that were flagged.
One example of an alert that we received when scanning one of our main repositories was the use of SHA1. Gosec has two rules for using SHA1:
- Importing the SHA1 package
- Using SHA1 as a hashing algorithm
These rules are
G401: Detect the usage of DES, RC4, MD5 or SHA1 and G505: Import blocklist: crypto/sha1
to help flag the inappropriate use of the cryptographically insecure SHA1 hash algorithm. We were using SHA1 for generating a unique identifier, rather than for the purpose of hashing, in a few locations within our API layer. For those instances, we weren’t concerned about the use of SHA1 being cryptographically insecure, since we weren’t interested in ensuring that we were preventing hash collisions.
In order to ignore lines of code that have been flagged, you can either globally ignore a specific rule or rules using a command like
gosec -exclude=G401,G505 ./… .
You could also ignore an alert caused by a specific line of code by using /* #nosec */ to ignore all rules, or /* #nosec G401 G505 */ to ignore specific rules.
We then investigated all other alerts, and addressed any valid findings with the appropriate teams. All other findings were ignored using the above patterns.
The final step was putting gosec into our CI/CD pipeline. We chose to trigger a scan on merge from master -> staging to prevent slowing down our automated testing. We calculated that by adding the scan from master to staging, it only added around 45 seconds of time to the build-scan-test and tear down process. This additional time was tolerable. Once all of this was set up, we submitted a pull request targeted at staging and have been running gosec ever since.