Skip to content

Add security CI baseline and update-integrity fuzz/adversarial evals#22

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

Add security CI baseline and update-integrity fuzz/adversarial evals#22
TeoSlayer merged 2 commits into
mainfrom
ci/security-hardening-fuzz-evals

Conversation

@TeoSlayer

Copy link
Copy Markdown
Contributor

Summary

Hardens CI security and adds adversarial/fuzz EVAL coverage for the updater's core security purpose: SHA256 checksum verification + SLSA attestation gating, fail-closed when gh is absent.

Net-new on top of the existing ci (test+coverage) and cascade workflows. No production behavior change beyond a defense-in-depth extraction cap and a toolchain bump; the fail-closed attestation contract already landed in #21 and is exercised by the evals here.

CI jobs added

security.yml

  • racego vet + go test -race ./... (security-scoped race gate, independent of coverage upload).
  • gosec — Go SAST (securego/gosec@v2.27.1).
  • govulncheck — known-vuln call-graph scan (golang/govulncheck-action@v1.0.4).
  • gitleaks — secret scan over history/PR range (gitleaks/gitleaks-action@v3.0.0).
  • dependency-review — PR-only, blocks high-severity vulnerable/incompatible deps (actions/dependency-review-action@v3).

codeql.yml

  • CodeQL Go analysis, security-extended queries, push + PR + weekly schedule (github/codeql-action@v4).

Dependabot.github/dependabot.yml already present (gomod weekly + github-actions weekly); requirement satisfied, unchanged.

All actions pinned to official released versions.

Scanner findings + resolutions

  • govulncheck: 2 findingsGO-2026-5039 (net/textproto) and GO-2026-5037 (crypto/x509), both Go stdlib, fixed in go1.25.11. Resolved by bumping go.mod to go 1.25.11. Re-scan: clean.

  • gosec: G110 (decompression bomb)io.Copy of tar entries had no size cap. Fixed in code: per-entry io.LimitReader(tr, maxDownloadBytes+1) with an over-cap error in extractTarGz.

  • gosec: accepted exclusions (documented inline in security.yml, minimal, never blanket):

    • G104 — best-effort os.Remove/Close on error-cleanup paths.
    • G204 — exec of gh/launchctl with internally-built args (no user input).
    • G301/G302 — install/staging dirs 0755; extracted artifacts are executables (must be 0755).
    • G304 — file paths derive from InstallDir/temp dir, inherent to an updater.
    • G404math/rand used only for thundering-herd jitter, not secrets.

    gosec exits 0 with these exclusions; never red, never blanket-disabled.

Evals added (adversarial / update integrity)

  • FuzzVerifyChecksum — fuzzes the checksums.txt line parser with adversarial inputs (malformed lines, embedded NULs, giant fields, duplicate/garbage lines, no trailing newline). Asserts: never panics; only returns nil when a line genuinely parses to the correct SHA256 for the archive name (independent cross-check guards against verification bypass). 21k+ execs, no crashes.
  • TestApplyUpdate_TamperedArchiveRefused — eval (e): valid checksums.txt for the original artifact, but the served archive bytes are swapped (MITM/CDN compromise). Asserts the update is refused and the on-disk daemon is left untouched.

Existing zz_*_test.go already cover the rest of the matrix and are confirmed green:

  • (a) SHA256 mismatch refused — TestApplyUpdate_ChecksumMismatch
  • (b) gh absent + SkipAttestation=false => fail closed — TestVerifyChecksumsAttestation_GhNotInstalled, TestVerifyChecksumsAttestation_FailsClosedWithoutSkip
  • (c) SkipAttestation=true skips attestation but SHA256 stays mandatory — TestApplyUpdate_SkipAttestationStillRequiresChecksum, TestVerifyChecksumsAttestation_SkipConfig
  • (d) happy path installs — TestApplyUpdate_PassesWithValidChecksums

Evals use the existing fakeable seams (verifyChecksumsAttestationFn, LookPath via PATH, httptest) — no real gh/network in CI.

Validation (GOWORK=off, go1.25.11)

go build ok · go vet ok · gofmt -l clean · go test -race ./... ok · FuzzVerifyChecksum 15s no crashes · govulncheck clean · gosec exit 0.

@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.

@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!

security.yml: golang/govulncheck-action does its own git fetch and
fails with 'unable to access ... 400' on org repos — run the tool via
'go run golang.org/x/vuln/cmd/govulncheck@latest ./...' after checkout
+ setup-go instead. Replace gitleaks/gitleaks-action (needs a paid
GITLEAKS_LICENSE secret for org repos) with the MIT-licensed pinned
gitleaks binary. Both match the green rendezvous/common pattern.

updater.go: CodeQL go/zipslip flagged extractTarGz as a high-severity
Zip Slip (CWE-022). filepath.Base already strips traversal, but add an
explicit destDir-containment check so the invariant is auditable and
CodeQL's dataflow recognises the sanitizer; reject escaping entries.
@TeoSlayer TeoSlayer merged commit 07ff073 into main Jun 22, 2026
9 checks passed
@matthew-pilot matthew-pilot deleted the ci/security-hardening-fuzz-evals branch June 22, 2026 15:48
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