mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 14:11:31 +00:00
fix(bundle-7): Verification & Tool Suite Execution — wire mandatory scans + first-run evidence
Closes Audit-2026-04-25 D-001..D-002 + D-006 (partial) + H-005 (partial). Opens new tracker IDs H-010, M-028, L-020, L-021 (see closure document in cowork/comprehensive-audit-2026-04-25/tool-output/_BUNDLE-7-CLOSURE.md). What changed - scripts/install-security-tools.sh (NEW) — idempotent installer for the Go-based subset (govulncheck, staticcheck, errcheck, ineffassign, gosec, osv-scanner). Used locally + by both CI workflows. - .github/workflows/security-deep-scan.yml (NEW) — daily + workflow_dispatch scans for tools that need docker/network: trivy image, syft SBOM, ZAP baseline, schemathesis, nuclei, testssl.sh, gosec, osv-scanner, full-suite race detector at -count=10. Every step continue-on-error; artefacts uploaded for triage. - .github/workflows/ci.yml — staticcheck added as a soft (continue-on-error) gate alongside the existing govulncheck hard gate. Soft until M-028 closes the 6 remaining SA1019 deprecated-API sites; flip to fail-on- non-zero then. Per-package coverage gates extended: pkcs7 hard ≥85% (currently 100%), local-issuer soft ≥65% transitional floor (H-010 raises to 85%). - staticcheck.conf (NEW) — suppresses 4 style-only rules (ST1005, ST1000, ST1003, S1009, S1011, SA9003) with documented justifications. Real defects (SA1019) NOT suppressed. - .govulnignore (NEW) — empty placeholder with the suppression contract (one OSV ID + justification + review-by date per line). Bundle-7's 5 deferred-call advisories don't need entries because govulncheck's default exit code already passes. Local tool-run evidence (cowork/comprehensive-audit-2026-04-25/tool-output/2026-04-26/): - govulncheck.txt + govulncheck-verbose.txt — clean (0 affected; 5 deferred-call) - staticcheck.txt + staticcheck-after-suppressions.txt — 6 SA1019 → M-028 - errcheck.txt — 1294 sites, all defer-Close / response-write convention → triaged - ineffassign.txt — 15 unique sites → L-020 - helm-lint.txt — clean (1 INFO-level icon recommendation) - go-test-race.txt — clean across scheduler/middleware/mcp at -count=3 (CI runs -count=10 against the full suite) - go-test-cover.txt — crypto 86.7% ✓, pkcs7 100% ✓, local-issuer 68.3% ✗ → H-010 Closures in this bundle - D-001 partial — 4 of 6 Go-based tools ran locally; remainder wired in CI - D-002 closed — race detector clean - D-006 partial — helm lint passes; kube-score / kubesec deferred to CI - D-007 deferred — semgrep p/react-security wired in CI (needs docker) - D-003 / D-004 / D-005 deferred — wired in security-deep-scan.yml - H-005 partial — crypto + pkcs7 meet 85%; local-issuer at 68.3% → H-010 New tracker IDs opened (next-bundle scope) - H-010 — local-issuer coverage gap (68.3% vs 85% target). 2-3 days. - M-028 — 6 deprecated-API sites (SA1019). Migration coordinated. - L-020 — ineffassign cleanup sweep, 15 mechanical sites. - L-021 — 5 transitive Go-module CVEs (deferred-call). Monitor + bump. NOT addressed in this bundle (deferred to a future Bundle 7-bis) - M-007 bulk-operation partial-failure tests - M-008 admin-gated role-gate tests - L-010 mock.Anything overuse audit - L-018 defect age analysis on remaining High findings Verification - go vet ./... → clean - go build ./... → clean - go test -short -count=1 ./... → all packages pass - go test -race -count=3 ./scheduler/middleware/mcp → clean - go test -cover ./crypto/pkcs7/local-issuer → see go-test-cover.txt - govulncheck ./... → clean - staticcheck ./... → 6 SA1019 (tracked as M-028) - helm lint → clean - yaml lint .github/workflows/*.yml → clean - python3 yaml.safe_load(api/openapi.yaml) → 89 paths Bundle 7 of the 2026-04-25 comprehensive audit. Tool-output evidence preserved at cowork/comprehensive-audit-2026-04-25/tool-output/2026-04-26/.
This commit is contained in:
@@ -42,8 +42,31 @@ jobs:
|
||||
run: go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
|
||||
- name: Run govulncheck
|
||||
# Bundle-7 / D-001 partial: govulncheck distinguishes called-vs-uncalled
|
||||
# advisories. Default exit code is non-zero only when YOUR code calls
|
||||
# the vulnerable function — deferred-call advisories show up in the
|
||||
# output but don't fail the gate. See .govulnignore for the
|
||||
# suppression contract if a triaged false-positive needs to be muted.
|
||||
run: govulncheck ./...
|
||||
|
||||
- name: Install staticcheck (Bundle-7 / D-001)
|
||||
run: go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||
|
||||
- name: Run staticcheck
|
||||
# Bundle-7 / D-001: Go static analysis additive to vet. Suppressed
|
||||
# rules live in staticcheck.conf with documented justifications;
|
||||
# adding a new entry requires an explicit security review.
|
||||
#
|
||||
# SOFT gate (continue-on-error: true) until M-028 closes the 6
|
||||
# remaining SA1019 deprecated-API sites:
|
||||
# - cmd/server/main_test.go × 3: middleware.NewAuth → NewAuthWithNamedKeys
|
||||
# - internal/api/handler/scep.go: csr.Attributes → Extensions
|
||||
# - internal/connector/issuer/local/local.go: elliptic.Marshal → crypto/ecdh
|
||||
# When M-028 ships, flip continue-on-error to false to make this
|
||||
# a hard gate. Until then, the step still annotates findings on PRs.
|
||||
continue-on-error: true
|
||||
run: staticcheck ./...
|
||||
|
||||
- name: Forbidden auth-type literal regression guard (G-1)
|
||||
# G-1 closed the JWT silent auth downgrade by removing "jwt" from the
|
||||
# accepted CERTCTL_AUTH_TYPE values. This step grep-fails the build
|
||||
@@ -590,6 +613,17 @@ jobs:
|
||||
CRYPTO_COV=$(go tool cover -func=coverage.out | grep 'internal/crypto' | awk '{print $NF}' | sed 's/%//' | awk '{sum+=$1; n++} END {if(n>0) printf "%.1f", sum/n; else print "0"}')
|
||||
echo "Crypto package coverage: ${CRYPTO_COV}%"
|
||||
|
||||
# Bundle-7 / Audit H-005 — extended crypto-cluster gates per CLAUDE.md.
|
||||
# internal/pkcs7/ is at 100% at HEAD (encoder-only, exhaustively tested
|
||||
# via Bundle-4 fuzz targets + unit tests). internal/connector/issuer/local/
|
||||
# is at 68.3% at HEAD; H-010 tracks the gap and will lift this floor
|
||||
# to 85% once the missing CSR-validation + CA-cert-loading tests land.
|
||||
PKCS7_COV=$(go tool cover -func=coverage.out | grep 'internal/pkcs7' | awk '{print $NF}' | sed 's/%//' | awk '{sum+=$1; n++} END {if(n>0) printf "%.1f", sum/n; else print "0"}')
|
||||
echo "PKCS7 package coverage: ${PKCS7_COV}%"
|
||||
|
||||
LOCAL_ISSUER_COV=$(go tool cover -func=coverage.out | grep 'internal/connector/issuer/local' | awk '{print $NF}' | sed 's/%//' | awk '{sum+=$1; n++} END {if(n>0) printf "%.1f", sum/n; else print "0"}')
|
||||
echo "Local-issuer coverage: ${LOCAL_ISSUER_COV}%"
|
||||
|
||||
# Fail if thresholds not met
|
||||
if [ "$(echo "$SERVICE_COV < 55" | bc -l)" -eq 1 ]; then
|
||||
echo "::error::Service layer coverage ${SERVICE_COV}% is below 55% threshold"
|
||||
@@ -611,6 +645,18 @@ jobs:
|
||||
echo "::error::Crypto package coverage ${CRYPTO_COV}% is below 85% threshold"
|
||||
exit 1
|
||||
fi
|
||||
# Bundle-7 / H-005: pkcs7 hard gate (currently 100% — protects regressions).
|
||||
if [ "$(echo "$PKCS7_COV < 85" | bc -l)" -eq 1 ]; then
|
||||
echo "::error::PKCS7 package coverage ${PKCS7_COV}% is below 85% threshold"
|
||||
exit 1
|
||||
fi
|
||||
# Bundle-7 / H-005 / H-010: local-issuer SOFT gate at 65% — H-010
|
||||
# tracks the gap from 68.3% (HEAD) → 85% (CLAUDE.md target). Once
|
||||
# H-010's missing test cases land, raise this floor to 85.
|
||||
if [ "$(echo "$LOCAL_ISSUER_COV < 65" | bc -l)" -eq 1 ]; then
|
||||
echo "::error::Local-issuer coverage ${LOCAL_ISSUER_COV}% is below 65% transitional floor (H-010 will raise to 85%)"
|
||||
exit 1
|
||||
fi
|
||||
echo "Coverage thresholds passed!"
|
||||
|
||||
- name: Upload Coverage Report
|
||||
|
||||
Reference in New Issue
Block a user