feat: comprehensive security hardening (10 findings)#27
Closed
feat: comprehensive security hardening (10 findings)#27
Conversation
Generate a cryptographically random 16-byte base64 nonce on every request,
store it in the Echo context as "csp-nonce", and embed it in the CSP
script-src and style-src directives. Add nonce="{{ .CSPNonce }}" to all
<script> and <style> tags in base.html, browser.html, and login.html.
Records method, path, status, remote_ip, and authenticated user access key for every request; mutating methods logged at INFO, safe methods at DEBUG.
…move CDN dependencies
Resolves 3-way merge conflicts between our 10-finding security hardening implementation and 8 upstream commits including: - Use utils.IsSecureRequest from upstream refactor (removes local copy) - Adopt registerPublicRoutes/registerProtectedRoutes/resolveMinioEndpoint structure - Keep our additions: rate limiter, POST logout, upload limit, audit log, static serving - Keep our CSRF fix (non-HTMX POSTs require token, not skip) - Update user_journey_test to use POST /logout
…ith CSP nonce policy
- C1: Replace GET /logout links in browser.html and settings.html with POST forms - C2: Pass initialized map to login renderer so CSP nonce is injected correctly - I1: Vendor Inter font (woff2) to views/static/fonts/, remove Google Fonts CDN - I3: Document intentional CookieHTTPOnly=false decision in csrf.go - I4: Replace log.Printf with slog.Warn in main.go and auth_service.go - I5: Assert status code field in audit log test
The 4-node MinIO cluster + app takes longer than 10s to fully start. Poll /health every 5s (up to 150s) so E2E tests only run once the app is confirmed ready, eliminating flaky login timeouts.
- Remove x-show from creds form in login.html (always-visible default tab,
Alpine.js initialization timing caused login timeouts in fresh browser context)
- Add waitForLoadState('domcontentloaded') in bucket_stats beforeEach after goto /login
- Fix user_management logout: replace broken a[href="/logout"] with
form[action="/logout"] button selector (logout is now a POST form)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Systematic security hardening across 10 findings from a full audit:
High severity
internal/middleware/csrf.go)/loginPOST: 10 req/min per IP, returns 429 (cmd/server/main.go)Medium severity
GET /logouttoPOST /logoutwith CSRF-protected form to prevent forced-logout attacksunsafe-inlinein CSP with per-request cryptographic nonce; inject into all templates and partialslog/slog) for all requests after auth; includes user, method, path, status, IPIRON_SESSION_KEYis absent or not 32 bytesLow / hardening
MAX_UPLOAD_SIZE)views/static/; removes all CDN dependencies from CSPMINIO_ENDPOINTis not set (useslocalhost:9000fallback)OIDC_ENABLED=true; routes are not registered by defaultAlso integrates upstream refactors:
utils.IsSecureRequest,registerPublicRoutes/registerProtectedRouteshelpers,resolveMinioEndpoint, andoidcEnabledFromEnv.Test plan
go test ./...)/loginwithout token returns 400/loginwith 11 rapid requests returns 429 on the 11thGET /logoutreturns 404;POST /logoutwith CSRF token redirects to/loginnonce-value; nounsafe-inlineAPP_ENV=production) with missing/short session key/static/(no CDN requests)GET /login/oauthreturns 404 withoutOIDC_ENABLED=true