Dependency scanning
make security runs three complementary scanners. One of them, semgrep, is a
merge gate; the other two are advisory, because both can surface a dependency
that cannot be fixed in the same pull request. This page is for whoever
decides how hard those gates should be.
The scanners
Section titled “The scanners”govulncheck (Go vulnerability checker)
Section titled “govulncheck (Go vulnerability checker)”- Tool:
golang.org/x/vuln/cmd/govulncheck, baked into the build image. - Invocation:
govulncheck ./...(make govulncheck). - Config: none. It checks the Go vulnerability database for known vulnerabilities in code the build actually reaches.
- In CI: advisory. The step runs with
continue-on-error: trueand posts its output to the job summary and as an artifact.
pnpm audit (frontend dependencies)
Section titled “pnpm audit (frontend dependencies)”- Tool:
pnpm audit, in thefrontend/directory. - Invocation:
pnpm audit --audit-level high(make pnpm-audit). - Severity:
highandcritical; low and moderate are not reported. - In CI: advisory, like govulncheck:
continue-on-error: true, with the output in the job summary and as an artifact.
semgrep (static analysis of the frontend)
Section titled “semgrep (static analysis of the frontend)”- Tool: the
semgrep/semgrep:1.174.0image, pinned in both the workflow andscripts/semgrep.sh. - Invocation:
semgrep scan --error --metrics=off --config p/typescript --config p/javascript frontend/src(make semgrep). - Config: the two registry rule packs above. There is no
.semgrep.yaml;.semgrepignorein the repo root excludes paths. - Scope: the frontend only. The Go side is covered by
gosecinsidegolangci-lint, so pointing semgrep at it would report the same findings twice. - In CI: a merge gate. The job has no
continue-on-error, and--errormakes any finding fail it.
Gates at a glance
Section titled “Gates at a glance”| Scanner | Reports | In CI | Locally (make) |
|---|---|---|---|
| govulncheck | any reachable vulnerability | advisory | ci-advisory |
| pnpm audit | high and critical |
advisory | ci-advisory |
| semgrep | any finding from the two rule packs | blocks | ci-required |
Running locally
Section titled “Running locally”# All threemake security
# Individuallymake govulncheckmake pnpm-auditmake semgrepmake semgrep needs Docker. It runs scripts/semgrep.sh, which copies the
sources into the container with docker cp rather than a bind mount: from a
devcontainer talking to the host’s Docker daemon, a bind mount resolves on the
host and comes up empty for any worktree other than the one the container was
started from.
.github/workflows/security.yaml runs on every pull request, on demand, and
on a weekly schedule (Mondays at 06:00 UTC) that re-checks dependencies nobody
touched against newly published advisories. It has no push trigger. Each
scanner is one job, and each runs only when its side of the tree changed:
govulncheck for Go changes, pnpm audit and semgrep for frontend changes.
The Makefile mirrors the split:
ci-advisory: -$(MAKE) govulncheck -$(MAKE) pnpm-auditThe leading - reports a failure without stopping the run, matching CI’s
continue-on-error: true. semgrep is in ci-required instead, alongside
lint and the other blocking checks.
Raising the bar
Section titled “Raising the bar”- govulncheck or pnpm audit as a gate. Remove
continue-on-error: truefrom the step insecurity.yaml, and move the target fromci-advisorytoci-requiredin theMakefileso local runs agree. - pnpm audit’s threshold. Change
--audit-level highin both the workflow and thepnpm-audittarget:criticalto quieten it,moderateto widen it. - semgrep’s rules. Add rule packs with further
--configflags, in bothsecurity.yamlandscripts/semgrep.sh, which must stay in step.
Related
Section titled “Related”- Dependency updates are automated: Dependabot opens weekly pull requests
for Go modules, the frontend, the user docs and GitHub Actions
(
.github/dependabot.yml). - SBOMs are not generated for releases yet (
sbom: falsein.goreleaser.yml).