1. Overview
Secure source code techniques are a set of practices that can be used to improve the security of source code. These techniques can help to identify and fix vulnerabilities in source code, prevent unauthorized access to source code, and protect source code from being modified.
Some common secure source code techniques include:
- Linting: Linting is the process of checking source code for errors and stylistic issues. It is done by using a lint tool, which is a program that analyzes source code and identifies potential problems. Lint tools can be used to check for a variety of errors, including syntax errors, semantic errors, style errors, and security vulnerabilities.
- Static application security testing (SAST): SAST is a type of security testing that analyzes source code, binary code, or byte code to identify security vulnerabilities. SAST tools can be used to find vulnerabilities in a variety of programming languages, including Go, Java, Python, C++, and C#.
- License scanning: License scanning is the process of identifying the licenses of third-party software components used in a software application. This is important because it helps to ensure that the application complies with the terms of the licenses, which can help to avoid legal problems.
These techniques can be used to improve the security of source code at all stages of the software development life cycle. Linting can be used to identify errors early in the development process, SAST can be used to find vulnerabilities before the code is compiled or deployed, and license scanning can be used to ensure that the application complies with the terms of the licenses.
Using these techniques can help to improve the security of source code and to reduce the risk of security breaches.
What you will learn
This lab will focus on the tools and techniques to secure software source code.
- Linting
- Static Application Security Testing
- License Scanning
All of the tools and commands used in this lab will be performed in the Cloud Shell.
2. Setup and Requirements
Self-paced environment setup
- Sign-in to the Google Cloud Console and create a new project or reuse an existing one. If you don't already have a Gmail or Google Workspace account, you must create one.
- The Project name is the display name for this project's participants. It is a character string not used by Google APIs. You can update it at any time.
- The Project ID is unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference the Project ID (it is typically identified as
PROJECT_ID
). If you don't like the generated ID, you may generate another random one. Alternatively, you can try your own and see if it's available. It cannot be changed after this step and will remain for the duration of the project. - For your information, there is a third value, a Project Number which some APIs use. Learn more about all three of these values in the documentation.
- Next, you'll need to enable billing in the Cloud Console to use Cloud resources/APIs. Running through this codelab shouldn't cost much, if anything at all. To shut down resources so you don't incur billing beyond this tutorial, you can delete the resources you created or delete the whole project. New users of Google Cloud are eligible for the $300 USD Free Trial program.
Start Cloud Shell Editor
This lab was designed and tested for use with Google Cloud Shell Editor. To access the editor,
- Access your google project at https://console.cloud.google.com.
- In the top right corner click on the cloud shell editor icon
- A new pane will open in the bottom of your window
- Click on the Open Editor button
- The editor will open with an explorer on the right and editor in the central area
- A terminal pane should also be available in the bottom of the screen
- If the terminal is NOT open use the key combination of `ctrl+`` to open a new terminal window
Environment Setup
Set the GOPATH to a single directory to simplify commands used in this lab.
export GOPATH=$HOME/gopath
Create a directory to hold our work
mkdir -p workspace
cd workspace
Clone the source code repo
git clone https://gitlab.com/gcp-solutions-public/shift-left-security-workshop/source-code-lab.git
cd source-code-lab
export WORKDIR=$(pwd)
3. Linting
Linting is used to check common style-based mistakes or defects related to syntax. Linting assists security by providing a common syntax pattern across multiple teams that leads to faster code reviews, knowledge sharing and clarity of code.
Additionally, Linting identifies common syntax mistakes that can lead to common vulnerabilities such as improper or less efficient use of libraries or core APIs.
Install the staticcheck
linking tool
go get honnef.co/go/tools/cmd/staticcheck@latest
Run the Go Linter (staticcheck) in the project root directory
staticcheck
Review the output
main.go:42:29: unnecessary use of fmt.Sprintf (S1039)
You get the error because http.ListenAndServe()
accepts a String, and the current code uses Sprintf
without passing variables to the string
Review the command exit status.
echo $?
In this case, since the command resulted in an error, the exit status will be 1 or greater. This is one method that can be used in a CI/CD pipeline to determine success/failure of the tool.
Edit the main.go
file, and fix the code:
- Comment out the line below
LINTING - Step 1
inside themain()
method, by adding leading slashes(//
). - Uncomment the two lines directly below the
LINTING - Step 2
inside themain()
method, by removing the leading slashes.
Re-run staticcheck
in the project root directory
staticcheck
The command should not return any results (i.e. an empty line.)
Inspect the exit status of the command.
echo $?
In this case, since the command did not result in an error, the exit status will be zero.
4. Static Application Security Testing
AST/Static security testing - Provides static code analysis looking for common weaknesses and exposures ( CWEs)
Install the AST tool (gosec
)
export GOSEC_VERSION="2.15.0"
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | \
sh -s -- -b $(go env GOPATH)/bin v${GOSEC_VERSION}
Run gosec
with policy file against the source code
gosec -conf policies/gosec-policy.json -fmt=json ./...
Output should be similar to this
{ "Golang errors": {}, "Issues": [ { "severity": "HIGH", "confidence": "LOW", "cwe": { "ID": "798", "URL": "https://cwe.mitre.org/data/definitions/798.html" }, "rule_id": "G101", "details": "Potential hardcoded credentials", "file": "/home/random-user-here/shift-left-security-workshop/labs/source-code-lab/main.go", "code": "31: \t// STEP 2: Change this and the reference below to something different (ie, not \"pawsword\" or \"password\")\n32: \tvar pawsword = \"im-a-cute-puppy\"\n33: \tfmt.Println(\"Something a puppy would use: \", username, pawsword)\n", "line": "32", "column": "6" } ], "Stats": { "files": 1, "lines": 89, "nosec": 0, "found": 1 } }
The tool has identified a potential issue: Potential hardcoded credentials
5. License Scanning
Licenses are important to security because they can legally require you to expose source code that you may not want to expose. The concept is called " copyleft" licenses that require you to expose source code if you use dependencies with those licenses.
Install golicense
mkdir -p /tmp/golicense
wget -O /tmp/golicense/golicense.tar.gz https://github.com/mitchellh/golicense/releases/download/v0.2.0/golicense_0.2.0_linux_x86_64.tar.gz
pushd /tmp/golicense
tar -xzf golicense.tar.gz
chmod +x golicense
mv golicense $(go env GOPATH)/bin/golicense
popd
Build the binary file
go build
Run the license check with the current policy file that does not allow "BSD-3-Clause" licenses
golicense policies/license-policy.hcl hello-world
NOTE: This should fail with similar output:
🚫 rsc.io/sampler BSD 3-Clause "New" or "Revised" License 🚫 rsc.io/quote BSD 3-Clause "New" or "Revised" License 🚫 golang.org/x/text BSD 3-Clause "New" or "Revised" License
Modify the policy file policies/license-policy.hcl
to move the "BSD-3-Clause" from the deny
list to the allow
list.
Re-run the license check
golicense policies/license-policy.hcl hello-world
NOTE: This should succeed with similar output:
✅ rsc.io/quote BSD 3-Clause "New" or "Revised" License ✅ rsc.io/sampler BSD 3-Clause "New" or "Revised" License ✅ golang.org/x/text BSD 3-Clause "New" or "Revised" License
6. Congratulations
Congratulations, you finished the codelab!
What you have learned
- Tools and techniques to secure source code
—
Last update: 3/23/23