Cyral subscribes to a security as code methodology to continuously maintain and monitor our security posture. If you are developing software in Golang, gosec is a great first step at implementing security as code in your CI/CD pipeline. In this blog we will talk about how to implement the static code analysis tool gosec from the Secure Go project. Gosec currently has a set of 31 rules that map to the Common Weakness Enumeration (CWE) framework. Those rules help to secure your code by covering 8 of the 2019 CWE Top 25 Most Dangerous Software Errors. You’ll need to take a multi step approach designed for your application to gain full coverage.
Static code analysis (SCA) also known as source code analysis or static program analysis, is a method of applying rules against source code in order to find software bugs. This is a great first step at automatically finding software bugs. Static analysis dates back to at least the early 1970’s and the PFORT Verifier for checking a FORTRAN program. The virtues of SCA even show up in a paper published in 1995, imploring its usage in industrial applications. Over the years a number of both commercial and free or open source static analysis tools have been created each with their own merits and limitations. For this post, we will cover gosec as it is incredibly fast and purely focuses on security rules. We will then show how easy it is to implement a lint solution for general bugs as well.
Implementing lint and gosec with GitHub Actions
Implementing gosec with GitHub Actions is incredibly simple. Simply create a new pull request with the sample action file already listed in the repo. To do so in a repo that has not been setup with GitHub actions before via CLI:
cd src/ #your top level source directory
git checkout -b feature/gosec-actions #create a new branch
mkdir -p .github/workflows
vi main.yml
In your main.yml file created above, copy and paste the following:
name: Run Gosec
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
tests:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
args: ./…
Commit your code and open a pull request and you can then see the output in the Actions tab:
You can now click into each of the portions of the tests and see the full logs.
Next week, a new version of gosec will be released allowing you to specify multiple arguments when implementing with GitHub Actions.
For example, you may be worried about breaking your existing builds and instead want it to run it without failing the build. To do so, you would use the following config:
name: Run Gosec
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
tests:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v2
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
args: -no-fail ./…
Once your tests run, you can now view them in GitHub and decide what action you would like to take. If you manually review the code and find a false positive, there are multiple different ways to annotate the code with the tag #nosec to ignore on future runs. For example:
import "md5" #nosec
The gosec documentation has further ways to annotate blocks and even modify configuration of specific rules to fit your project.
To enable linting of your project you can use the authors of golangci-lint official GitHub action.
Implementing lint and gosec with GCP Cloud Build
Since you’re working with Golang, you may instead be running Cloud Build on GCP. If you are, you can use the following config in your cloudbuild.yaml and cloudbuild.release.yaml files:
# Run security tests
- name: securego/gosec
env:
- 'GO111MODULE=on'
args:
- -no-fail #don't fail the build
- ./...
volumes:
- name: 'go-modules'
path: /go
id: 'security-tests'
waitFor: ['unit-tests'] #wait for another step to finish
# Run lint
- name: golangci/golangci-lint
env:
- 'GO111MODULE=on'
args:
- golangci-lint
- run
- --issues-exit-code=0 #don't fail the build
volumes:
- name: 'go-modules'
path: /go
id: 'run lint'
waitFor: ['unit-tests']
Once they run, you can then click through your build steps to see what failed:
Next Steps: Implementing Security as Code
gosec and golangci-lint are great ways to begin with security as code for your Golang projects. We’ve taken you through 2 different build systems, but there are multiple ways to add them to your CI/CD pipeline or even run them locally. If you’re looking to continue your security as code journey with gosec, I would suggest editing your configuration to output a file that you can then import into another system to be able to follow up with the results. One of the projects that we mentioned in The Security Digest this week was DefectDojo. DefectDojo can import gosec results in JSON format and has a ton of other plugins as well.
#TogetherWeDefendBetter