gosec
- Control:
sast - Tool: gosec, https://github.com/securego/gosec
- Status: ✅ implemented
- Target: source repository (
RepositoryTarget), checked out at the scanned revision - License / terms: Apache-2.0 (permissive). Exec only, do not bundle or import.
What it does
A Go-specialized static analyzer that complements the polyglot Semgrep with
deeper Go-specific rules (AST/SSA). Checks out the component's repository and runs
gosec -fmt sarif -no-fail -track-suppressions -concurrency 2 <module>/... once per Go module, for every
directory holding a go.mod outside vendor/ and testdata/. A module below the root and a
module nested inside another are each analyzed, and each finding is located under its own
module's directory. A tree with no go.mod is reported as analyzed by nothing, never as clean.
A component scoped by paths to part of a module shares an analysis of the whole module, and keeps
only the findings in its own files. Scoping a
repository has the rule for shared code
no component names.
-no-failkeeps the process successful when findings exist (findings live in the SARIF report, not the exit code; thesastcontroller judges severity).-track-suppressionskeeps a#nosecresult in the report, marked, carrying the text after the--as its justification. Without it gosec removes the result, and a finding somebody excluded reads as a finding nobody ever made.-quietis deliberately not used: it suppresses all output on a clean scan, which would leave no SARIF to parse.-concurrency 2loads two packages at once, each building with-pat half of the parallelism bound n, rounded down, so the compile processes of both loads together stay within n. Where n is 1, gosec loads one package at a time. A-palready in yourGOFLAGSis kept.
Severity
gosec rates each rule HIGH, MEDIUM or LOW, and a finding's severity is that rating: high,
medium or low. gosec writes SARIF level error for HIGH and MEDIUM rules alike and records the rating as
a tag on the rule, so Draugr reads the tag rather than the level. A rule without a rating tag keeps
the level gosec wrote.
What a #nosec becomes
gosec reports it as a SARIF suppression of kind inSource, which Draugr keeps and marks with
origin: tool. It is the weakest of the three
origins and counted apart from them: a comment beside the line was written by whoever was editing
the file, and nothing about it went past a second person.
/* #nosec G204 -- the name is a constant in this program, reviewed 2026-09-22 */
_ = exec.Command("sh", "-c", name)
Opt-in
gosec is Go-only, so it doesn't run by default. Enable it under the sast control, where it runs
beside Semgrep:
config:
controls:
sast:
enabled: true
gosec:
enabled: true
The same key works as a per-component override. Only enable gosec for Go components. It errors on repositories with no Go packages.
Saga options
config:
controls:
sast:
gosec:
enabled: true
exclude: [G104] # rules that do not apply to this codebase
tags: [integration] # code behind a build tag gosec does not build, it does not analyze
| Option | What it does |
|---|---|
include | Run only these rule IDs (-include). |
exclude | Skip these rule IDs (-exclude). |
tags | Go build tags to compile with (-tags). |
gosec's -severity and -confidence floors are deliberately not exposed. Both drop findings
inside the tool, where Draugr cannot mark them suppressed or record who accepted them. A finding
you have judged belongs in config.exclude, which keeps it in the report with your reason; what
should fail a build is the gate's decision. Selecting rules is a different statement. That a
check does not apply to this codebase at all.
Notes
- Integration mode: exec over a local checkout;
gosec+gitmust be onPATH(draugr tools install gosecprovisions a pinned, SHA-256-verified copy). - gosec loads a module's packages with
go, so Go must be onPATHtoo. Without it gosec exits 0 having analyzed nothing, and the scan fails the control withgosec needs Go, and no `go` is on PATHrather than reporting the module clean. A tree holding no module runs nothing and needs no Go. - gosec and govulncheck take turns loading Go packages across the whole run, so this scanner's
job can wait for another load to end; the wait is in
stats.orderWaitsMs. - gosec signs its releases with a key-based cosign bundle; Draugr's identity-based signature
verification (used for Trivy) doesn't cover that yet, so
tools installverifies gosec by SHA-256 only for now.
Data
Nothing. gosec's rules are compiled into its binary.