Skip to content

feat: v2.5.0 — Go 1.27 migration & codebase hardening - #114

Open
had-nu wants to merge 19 commits into
mainfrom
feat/v2.5.0-go127
Open

feat: v2.5.0 — Go 1.27 migration & codebase hardening#114
had-nu wants to merge 19 commits into
mainfrom
feat/v2.5.0-go127

Conversation

@had-nu

@had-nu had-nu commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Summary

This PR implements the Wardex v2.5.0 specification: Go 1.27 migration and structural hardening.

Eixo A — Go 1.27 Migration

  • Updated go.mod to go 1.27.0
  • Updated CI workflows (.github/workflows/ci.yml, docker.yml, release.yml)
  • Updated Dockerfile base image
  • Ran go fix ./... and resolved modernizations

Eixo B — Architecture & Hardening

  1. pkg/orchestrator — Extracted orchestration logic from main.go and cmd/evaluate (God objects)
  2. pkg/cli/safefile.go — Centralized SafeReadFile/SafeWriteFile (was duplicated in ~15 files)
  3. log/slog migration — Replaced ad-hoc fmt.Fprintf(os.Stderr, ...) logging across pkg/* and cmd/*
  4. context.Context propagation — In pkg/epss, pkg/provenance, internal/notification
  5. pkg/accept refactor — Split into store, verify, audit, cli, rules, forward sub-packages
  6. Manual sorting replaced — Using slices.SortFunc
  7. Fuzz tests strengthened — Added property-based invariants

Testing

All tests pass:

go test ./...  # PASS
go test -race ./...  # PASS

Breaking Changes

  • trust.FetchTrustStore(ctx, path) and trust.SealConfig(ctx, ...) now require context.Context as first parameter
  • pkg/accept internal structure changed (public API preserved)

Closes: #v2.5.0-tracking

had-nu added 19 commits August 20, 2026 15:01
…feWriteFile/ReadFile); zero os.ReadFile+nosec outside
…+ deprecated facade; move ConfigHash->internal/cpl, ReadReport->pkg/report; replace bubble-sorts with slices.SortFunc
…n main/evaluate entry points

EvaluationPipeline runs the root wardex flow (config, correlation, gap analysis,
gate, snapshot, report, exit code) without os.Exit or direct os.Stderr writes,
logging through an injected *slog.Logger. RunGate owns the cmd/evaluate flow,
returning the exit code for the caller to apply.

main.go runWardex (28 lines) and cmd/evaluate runEvaluate (26 lines) now delegate
all orchestration. config.ApplyProfile accepts io.Writer; forward syslog windows
stub implements the ctx-based Send signature.
…ngci-lint clean

- pkg/orchestrator coverage 83.5%: evaluation pipeline tests (basic flow,
  gate blocked, compliance fail, snapshot delta, missing config, invalid
  framework, min-confidence filter), gate pipeline tests (allow/block,
  strict unsealed, missing-EPSS, dry-run, csv/json output, sealed wexstate
  config, state store + trend, Article 14 active exploitation), and helper
  unit tests (gateLabel, riskColor, dryRunGate, hintMissingEPSS, overrides,
  formatDuration, isCI).
- Fix collectCLIOverrides to not treat the zero-value gate mode as override.
- Fuzz tests with property invariants: ingestion (id/name/maturity/layer/
  context-weight invariants; caught and fixed unvalidated layer coercion
  in validateControl), pathguard (no workspace escape, null/overlong and
  pseudo-fs paths always rejected), verify (sign/verify round-trip, tamper
  and wrong-key rejection, corrupted batch signatures).
- go test -race ./... passes; golangci-lint v2.13.1 (built with go1.27) clean.
- CI pins golangci-lint v2.13.1 for the Go 1.27 module.
- CHANGELOG: add [2.5.0] entry covering Go 1.27 migration, orchestrator,
  safefile, slog, context propagation, pkg/accept decomposition, sorting,
  fuzzing, and lint/race hardening.
- README (pt/en): document Go >= 1.27 requirement; Go badge to 1.27.
- main.go: Version 2.5.0.
- wardex-config.yaml: provenance node_id wardex-release-v2.5.0.
- pkg/ingestion: benchmarks for LoadYAML/LoadJSON/LoadCSV/LoadMany with
  100-control fixtures; fixture setup excluded from the measured loop.
- pkg/epss: benchmarks for Sign/Verify over 100-enrichment payloads.
- doc/benchmarks/wardex-v2.5.0.md: baseline table satisfying the spec's
  no-regression comparison reference.
- .golangci.yml: enable gomodguard_v2 (gomodguard deprecated in v2.12.0);
  lint now runs warning-free with 0 issues.
- .gitignore: anchor benchmarks/ to repo root so doc/benchmarks can be tracked.
Critical fixes:
1. PathGuard symlink bypass (CVE-class): Fixed validatePath to check symlinks
   in parent directories of non-existent output files. Added
   resolveWithSymlinkCheck that walks path components and validates
   each existing component for symlink escapes. Added
   TestValidateOutputPath_SymlinkParentEscape.

2. Trust Store metadata manipulation: Enhanced VerifyRootSig to verify
   each KeyEntry.AddedSig against AddedBy signer, and each
   Revocation.Sig against RevokedBy admin signer. Previously only
   RootSig was verified, allowing role escalation via metadata
   modification.

3. Risk Acceptance hash validation: Added ConfigHash field to
   model.Acceptance and updated VerifyAll to check ReportHash and
   ConfigHash against current values. Set ReportMismatch and Stale
   flags appropriately.

4. NaN/Inf fail-open in risk engine: Added isValidScore validation
   in CalculateRisk for CVSSBase, EPSSScore, Criticality, and
   Effectiveness. Returns maximum risk (BLOCK) on NaN/Inf/out-of-range.

5. Arbitrary file write via os.WriteFile: Migrated 10 commands
   (art14, chain/seal, convert/grype/kev/sbom, policy, simulate,
   provenance/seal) to use cli.SafeWriteFile/cli.SafeOutputPath.

6. Atomic write symlink attack: Updated atomicwrite.Write to use
   os.CreateTemp with O_EXCL instead of path + '.tmp'.

Tests: All fuzz tests pass (pathguard, ingestion, accept/verify),
race detector clean, golangci-lint 0 issues.
- pkg/cli/pathguard.go: use strings.SplitSeq and range over iterator
- pkg/epss/epss_benchmark_test.go: use range over int
- pkg/ingestion/ingestion_benchmark_test.go: use range over int
The v1.1.4 crashes with panic when running on Go 1.27. v1.6.0 is the
latest stable version compatible with Go 1.27.
Will re-enable when gosec releases a compatible version.
- CHANGELOG: comprehensive v2.5.0 entry covering all 12 critical security fixes,
  architecture hardening, tests/fuzzing, and breaking changes.
- README.md / README-en.md: added v2.5.0 security hardening section with
  all 12 critical fixes, architecture hardening, tests/fuzzing; added
  Security badge.
- pkg/atomicwrite: 14 unit tests + 2 fuzz tests covering basic ops,
  atomicity, symlink attacks, overwrite, context cancellation, large data,
  permissions, directory sync, and concurrent writes. Fuzz tests find
  5+ interesting inputs.

- pkg/accept/store: 18 unit tests + 2 fuzz tests covering Load (empty,
  valid, tampered, expired, report/config hash mismatch, empty hashes),
  Append (new file, append, atomicity, concurrent), UpdateStatus
  (revoked, not found), AuditLog integration, LogsRejections.
  Fixed race in Append with file-path mutex. Fixed audit consistency
  check to only apply when auditPath provided.

- pkg/atomicwrite: fixed ineffassign lint in test.

All tests pass with -race, golangci-lint 0 issues.
- pkg/accept/forward: 18 unit tests + 3 fuzz tests covering
  ForwardMultiplexer (block/warn/best_effort policies, multiple backends),
  NotifyMultiplexer, WebhookNotifier (success, template error, HTTP error,
  timeout, unconfigured event), ENISABackend.
  Fuzz tests cover multiplexer dispatch, webhook notify, ENISA backend send.

- pkg/accept/audit: 11 unit tests + 2 fuzz tests covering
  AuditLog (basic, UTC timestamp, zero timestamp, thread-safe, new file,
  permissions, invalid JSON), AuditCountCreated (empty, nonexistent,
  counts created, ignores other events, malformed line, empty lines).
  Fuzz tests cover log and count functions.

All tests pass with -race, golangci-lint 0 issues.
- pkg/trust/fetch_test.go: Add context.Context to all FetchTrustStore calls
- pkg/trust/trust_test.go: Add context.Context to SealConfig call
- Both files: Add context import
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.

1 participant