Skip to content

Add security CI scanners and trust-loader fuzz evals#22

Merged
TeoSlayer merged 2 commits into
mainfrom
harden/ci-security-fuzz-evals
Jun 22, 2026
Merged

Add security CI scanners and trust-loader fuzz evals#22
TeoSlayer merged 2 commits into
mainfrom
harden/ci-security-fuzz-evals

Conversation

@TeoSlayer

@TeoSlayer TeoSlayer commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Hardens CI security and adds adversarial/fuzz EVAL coverage to the trust-decision logic. Also fixes a genuine pre-existing test-suite data race uncovered during validation. No production code behavior changes.

New CI gating checks (.github/workflows/security.yml)

Job Purpose
go test -race GOWORK=off go test -race -parallel 4 ./... as a standalone hard gate
govulncheck known-CVE scan over the reachable call graph (deps + stdlib)
gosec Go SAST; SARIF to the Security tab; job fails on any finding
gitleaks secret scan over git history (binary, license-free)
codeql semantic SAST for Go, security-extended query suite
dependency-review PR-only; blocks vulnerable / bad-license dependency additions (fail-on-severity: moderate)

All actions pinned to official major-version tags. Workflow-level permissions: contents: read; only CodeQL/gosec widen to security-events: write. actionlint clean. All six jobs pass green on this PR.

.github/dependabot.yml (gomod + github-actions, weekly) already exists on main.

Scanner findings + resolutions

  • gosec: 0 findings. No rules disabled, no #nosec.
  • gitleaks: 0 leaks (working tree + 40 commits of history). gitleaks-action@v2 now requires a paid GITLEAKS_LICENSE for org repos, so the job runs the gitleaks binary directly — identical scan, no license.
  • govulncheck: 2 stdlib advisories (GO-2026-5039 net/textproto, GO-2026-5037 crypto/x509), both fixed in go1.25.11. Resolved by pinning CI to go-version: '1.25' (latest patched 1.25.x on runners). No code change, no exclusions.
  • dependency-review: required enabling the repo Dependency Graph (vulnerability-alerts) — done; job now passes.
  • Accepted/documented exclusions: none.

Adversarial / fuzz evals (zz_fuzz_test.go)

Extends the deterministic pin matrix in zz_pubkey_pin_test.go (PR #21) without duplicating it:

  • FuzzLoad — arbitrary bytes into Load: never panics; on success the index is fail-closed (no zero/empty entries, no oversized pins) and a pinned node never trusts a random key. Seeds cover valid / malformed / oversized / duplicate / pinned / bad-base64 / short-key / deeply-nested.
  • FuzzDecodePin — arbitrary strings into the pin decoder: never panics; returns an error or a key of exactly ed25519.PublicKeySize; empty → (nil,nil).
  • TestLoad_OversizedDocDoesNotPanic — 50k-entry doc loads without wedging.
  • TestLoad_DuplicateWithPinsRejected — duplicate node_id with conflicting pins is rejected; neither pin becomes trusted.

Existing matrix already confirms: pinned+correct ⇒ trusted, pinned+wrong ⇒ not, pinned+empty/short ⇒ not, unpinned ⇒ node_id trust (backward compat), unknown ⇒ not, constant-time compare (crypto/subtle).

Pre-existing test-race fix (zz_test.go)

The four SetForTest-based tests in zz_test.go were marked t.Parallel() while each swaps the single global allowlist, so concurrent runs observed one another's state. The original suite failed under -parallel 8 -count=20 (TestAllReturnsCopy, TestZeroNodeIDIgnored). Dropped t.Parallel() from those four to match the (correctly non-parallel) SetForTest tests in zz_pubkey_pin_test.go / zz_service_test.go. Suite now green across 30 consecutive -race runs at parallelism 8 and 4.

Validation (GOWORK=off)

  • go build ./... / go vet ./... — OK
  • gofmt -l . — clean
  • go test -race -parallel 8 -count=30 and -parallel 4 -count=30 — OK
  • FuzzLoad / FuzzDecodePin — ~62k / ~34k execs, no crashers
  • gosec / gitleaks — 0 findings
  • actionlint — clean

Add a security workflow (race-gated test, CodeQL security-extended,
gosec SARIF, govulncheck, gitleaks, PR dependency-review) alongside the
existing dependabot gomod/actions config.

Add adversarial fuzz coverage for the trust decision loader: FuzzLoad
asserts Load never panics on malformed/oversized/duplicate input and
stays fail-closed, FuzzDecodePin pins the pin-decoder contract, plus
deterministic oversized-doc and duplicate-with-pins guards.

Drop t.Parallel from TestLoadDuplicateNodeID: it mutates and asserts on
shared global state, so concurrent global-mutating tests could race its
post-Load assertion.
@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Drop t.Parallel from the SetForTest-based tests in zz_test.go: each
swaps the single global allowlist, so running them concurrently let
their post-swap assertions observe another test's state. The original
suite failed under -parallel 8 -count=20; it now passes 30x at -race.

Run gitleaks as a binary instead of gitleaks-action@v2, which requires
a paid license for organization repos. Same git-history scan, no
license needed.
@TeoSlayer TeoSlayer merged commit dd46550 into main Jun 22, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants