Automate your Static Application Security Testing (SAST)#
Static Application Security Testing (SAST) is a type of security testing that is run on the source code, byte code, or binary code of an application without running the application itself.
One of the most popular SAST tools is the open source tool Semgrep, which will scan your source code for vulnerabilities, secrets leakage, and other issues according to a set of rules for each supported language, outputting a list of results that can be addressed by the security team.
Chalk supports Semgrep integration out of the box, and other SAST tools can be added via the tools plugin.
Let’s see how.
Load Chalk configuration#✦
Make sure you have a working Installation Guide of Chalk.
Now enable the builtin SAST tools to run during build.
chalk load https://chalkdust.io/run_sast.c4mYou can check that the configuration has been loaded by running:
$ chalk dumpNow let’s take a look how SAST works with and without Docker.
SAST without Docker#✦
Grab the Caddy sources (a webserver in Go) and build it.
git clone https://github.com/caddyserver/caddy
cd caddy
go build ./cmd/caddyNow run chalk insert ./caddy to Chalk the binary.
$ chalk insert ./caddy > /dev/null
info: attestation: signing file /home/admin/caddy/caddy
info: /home/admin/caddy/caddy: chalk mark successfully added
info: /home/admin/.local/chalk/chalk.log: Open (sink conf='default_out')
info: Full chalk report appended to: ~/.local/chalk/chalk.logThe SAST report is included in the report generated by chalk insert. We can
extract it with jq.
jq -c -r '.[]|.SAST.semgrep' ~/.local/chalk/chalk.log | tail -n1 > sast.jsonThe Semgrep output is deeply nested so a jq query to pretty-print
the results is gnarly, but you can use this as a starting point.
$ jq -r '.runs[]|.results[]|[.message.text[0:40], "...", (.locations[]|.physicalLocation.artifactLocation.uri[-25:]), ":", (.locations[]|.physicalLocation.region.snippet.text[0:40]|split("\n")[0])] | join (" ")' sast.json | head -n 10
Using variable interpolation `${{...}}` ... lows/release-proposal.yml : run: |
Using variable interpolation `${{...}}` ... lows/release-proposal.yml : run: |
Using variable interpolation `${{...}}` ... lows/release-proposal.yml : run: |
Using variable interpolation `${{...}}` ... lows/release-proposal.yml : run: |
Detected directly writing or similar in ... home/admin/caddy/admin.go : _, err = w.Write(buf.Bytes())
Insecure WebSocket Detected. WebSocket S ... ttpcaddyfile/addresses.go : return nil, fmt.Errorf("the scheme ws:
`MinVersion` is missing from this TLS co ... caddyconfig/httploader.go : tlsConfig = &tls.Config{Certificates:
`MinVersion` is missing from this TLS co ... caddyconfig/httploader.go : tlsConfig = &tls.Config{Certificates:
`MinVersion` is missing from this TLS co ... caddyconfig/httploader.go : tlsConfig = new(tls.Config)
Detected directly writing or similar in ... caddy/caddyconfig/load.go : _, _ = w.Write(respBody) //nolint:gosEmbedding the SAST report#✦
While we could also embed the SAST report into the binary like we can with SBOM reports, you should think carefully about doing this. You don’t want to ship your binary along with a list of vulnerabilities.
If you have a good reason to embed the SAST report you can do so by loading:
chalk load https://chalkdust.io/embed_sast.c4mNow let’s take a look at generating SAST reports from Chalk for Docker images.
SAST with Docker#✦
Things are a little different in Docker world. First off we cannot use
chalk insert to inject a container because containers are
immutable. Instead, Chalk wraps Docker build commands and injects
Chalk marks into the container during the build process.
Let’s build Curl via Docker and view its SAST report.
Curl sources#✦
First, grab the Curl sources.
cd ~
git clone https://github.com/curl/curl
cd curlNow build the image with Chalk.
chalk docker build .Chalk will generate a build report when we do this which will
include the SAST report. We can extract the SAST report with jq.
jq -c -r '.[]|.SAST.semgrep' ~/.local/chalk/chalk.log | tail -n1 > sast.jsonAnd we can pretty-print the SAST JSON report with jq.
$ jq -r '.runs[]|.results[]|[.message.text[0:40], "...", (.locations[]|.physicalLocation.artifactLocation.uri[-25:]), ":", (.locations[]|.physicalLocation.region.snippet.text[0:40]|split("\n")[0])] | join (" ")' sast.json | head -n 10
Insecure WebSocket Detected. WebSocket S ... cs/internals/WEBSOCKET.md : using the `ws://` or `wss://` URL scheme
Insecure WebSocket Detected. WebSocket S ... cs/internals/WEBSOCKET.md : If the given WebSocket URL (using `ws://
Insecure WebSocket Detected. WebSocket S ... pts/CURLOPT_WS_OPTIONS.md : curl_easy_setopt(curl, CURLOPT_URL,
The special variable IFS affects how spl ... jects/OS400/initscript.sh : IFS="/"
The special variable IFS affects how spl ... jects/OS400/initscript.sh : do IFS="${IFSSAVE}"
The special variable IFS affects how spl ... jects/OS400/initscript.sh : IFS="${IFSSAVE}"And this might not look like it’s reporting anything meaningful but
this is indeed what you’d get if you run semgrep scan --config auto
on the Curl repo. Curl is in good shape!