Skip to content

fix(hardening): close DoS, traversal, and crypto-correctness gaps#8

Merged
tzone85 merged 1 commit into
mainfrom
hardening/audit-fixes-2026-06-17
Jun 17, 2026
Merged

fix(hardening): close DoS, traversal, and crypto-correctness gaps#8
tzone85 merged 1 commit into
mainfrom
hardening/audit-fixes-2026-06-17

Conversation

@tzone85

@tzone85 tzone85 commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Summary

Codebase audit pass. Build, go vet, golangci-lint (0 issues), the full race test suite, and the per-package coverage gate (global 88.2% ≥ 87.0%) all pass. Every behavioural change has a test.

Security / robustness

Area Fix
api body limit http.MaxBytesReader (8 MiB) + baseline security headers (nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer) via router middleware. NewMux now returns http.Handler.
api policy bomb Cap policy_yaml at 64 KiB before policy.Parse (alias/anchor-bomb defence); returns 413.
cli serve timeouts Add ReadTimeout/WriteTimeout/IdleTimeout — closes Slowloris-class goroutine pinning.
cli tenant traversal Root PersistentPreRunE validates --id before any subcommand builds a path; tenant.ValidateID added; tenantSubdir/defaultIngestOutPath use filepath.Join.
mcp hash validation themis_bom hash validated as 64 lowercase hex chars before composing the URL path.
sign cert expiry CosignKeylessStub.Verify now enforces the cert validity window instead of silently accepting expired certs.
auth/oidc token cache Cache keyed on sha256(token) (no plaintext tokens in memory); IdP call bounded by a 10s timeout.

Correctness / best practices

  • api/overrides: handleOverrideClosePM no longer discards the readTenantEvents error (was a silent 200 with empty state).
  • mcp: request context threaded through handleLine → handleToolCall → httpGET so outbound calls are cancellable.
  • heartbeat: removed the dead single-goroutine mutex in Watch.
  • Removed three "keep imports tidy" blank-identifier hacks (errors/filepath/strings) and their unused imports.

Out of scope (noted, not changed)

  • OIDC not wired into the request path (RequireIdentity hardwires FileTokenStore). This is documented Plan-18 future work and needs an operator-facing config mechanism to select the store — a feature, not a bug fix.
  • tokens revoke substring matching is intentional/documented operator behaviour.

Test plan

  • go build ./..., go vet ./...
  • golangci-lint run ./... → 0 issues
  • go test -race ./... → all pass
  • coverage gate (scripts/cover_check.sh) → PASS

…move import hacks

Audit pass over the whole codebase. Each item is substantiated by reading
the affected code; tests added for every behavioural change.

Security / robustness
- api: bound request bodies with http.MaxBytesReader (8 MiB) and set
  baseline response headers (nosniff, X-Frame-Options DENY, no-referrer)
  via a router middleware. NewMux now returns http.Handler.
- api: cap policy_yaml at 64 KiB before policy.Parse so a YAML alias/anchor
  bomb cannot burn CPU in the parser (413 on oversize).
- cli(serve): add ReadTimeout/WriteTimeout/IdleTimeout so a slow-body or
  slow-read client can no longer pin a handler goroutine (Slowloris).
- cli(root): validate the --id flag in a PersistentPreRunE so a scripted
  `--id ../../etc` is rejected before any subcommand builds a tenant path.
  Adds tenant.ValidateID; tenantSubdir/defaultIngestOutPath now use
  filepath.Join instead of string concatenation.
- mcp: validate the themis_bom hash as 64 lowercase hex chars (matching the
  REST layer) before composing the URL path.
- sign: CosignKeylessStub.Verify now enforces the certificate validity
  window instead of silently accepting expired/not-yet-valid certs — the
  short-lived-cert property is the security premise of keyless signing.
- auth(oidc): key the userinfo cache on sha256(token) so a heap dump cannot
  leak live bearer tokens, and bound the IdP call with a 10s timeout so a
  stalled IdP cannot hang the handler.

Correctness / best practices
- api(overrides): handleOverrideClosePM no longer discards the
  readTenantEvents error (was returning 200 with empty state on failure).
- mcp: thread the request context through handleLine → handleToolCall →
  httpGET so outbound API calls are cancellable.
- heartbeat: drop the dead single-goroutine mutex in Watch.
- Remove three "keep imports tidy" blank-identifier hacks
  (errors/filepath/strings) and their now-unused imports.
@tzone85 tzone85 merged commit f94c5ef into main Jun 17, 2026
2 checks passed
@tzone85 tzone85 deleted the hardening/audit-fixes-2026-06-17 branch June 17, 2026 19:50
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