fix: prevent browser caching of sensitive pages over HTTPS - #1194
fix: prevent browser caching of sensitive pages over HTTPS#1194DevipriyaS17 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds explicit anti-caching response headers to prevent browsers from storing authenticated API responses and the UI shell/fallback HTML, reducing the risk of sensitive content being retrievable from shared machines.
Changes:
- Introduced reusable
setNoCacheHeaders+noCacheHeadersMiddlewareand applied them to/api/*routes. - Ensured UI document responses (
/and SPA fallback) are served with no-cache/no-store headers. - Added unit tests to validate no-cache headers for the UI fallback and the middleware.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| internal/controller/httpapi/router.go | Adds no-cache constants/helpers and applies middleware to /api routing. |
| internal/controller/httpapi/ui.go | Adds no-cache headers to UI root and SPA fallback document responses. |
| internal/controller/httpapi/ui_test.go | Adds tests asserting no-cache headers for UI fallback and middleware behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1194 +/- ##
==========================================
+ Coverage 50.09% 50.61% +0.51%
==========================================
Files 146 146
Lines 13552 13574 +22
==========================================
+ Hits 6789 6870 +81
+ Misses 6171 6105 -66
- Partials 592 599 +7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (3)
internal/controller/httpapi/ui.go:88
- Same issue in the SPA fallback: using
FileFromFS("./", ...)targets a directory. Servingindex.htmlexplicitly avoids directory listing / inconsistent responses when the embedded UI isn't present.
setNoCacheHeaders(c)
c.FileFromFS("./", http.FS(staticFiles))
})
internal/controller/httpapi/ui.go:48
- Serving the UI shell via
FileFromFS("./", ...)points at a directory, which can yield inconsistent behavior (e.g., directory listing or a redirect/404) whenindex.htmlis missing. Since this route is intended to serve the SPA shell, serveindex.htmlexplicitly.
handler.GET("/", func(c *gin.Context) {
setNoCacheHeaders(c)
c.FileFromFS("./", http.FS(staticFiles))
})
internal/controller/httpapi/ui_test.go:120
- This test assumes the embedded UI root always returns 200, but in this repo the embedded
ui/directory can be empty (e.g., local builds), so the handler may legitimately return 404. The assertion should focus on the no-cache headers rather than a fixed status code.
require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, cacheControlNoStore, w.Header().Get("Cache-Control"))
require.Equal(t, pragmaNoCache, w.Header().Get("Pragma"))
require.Equal(t, expiresNoCache, w.Header().Get("Expires"))
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (4)
internal/controller/httpapi/ui_test.go:127
- This test runs in parallel but calls
setupUIRoutes, which writes a fixed filename to the process temp dir (seeinjectConfigToMainJSusingos.TempDir()/main.js). Parallel runs can race/flap by clobbering the same temp file; isolate the temp dir per test (or avoid running these in parallel).
t.Parallel()
engine := gin.New()
setupUIRoutes(engine, logger.New("error"), &config.Config{})
internal/controller/httpapi/ui_test.go:110
- This test runs in parallel but calls
setupUIRoutes, which writes a fixed filename to the process temp dir (seeinjectConfigToMainJSusingos.TempDir()/main.js). Parallel runs can race/flap by clobbering the same temp file; isolate the temp dir per test (or avoid running these in parallel).
t.Parallel()
engine := gin.New()
setupUIRoutes(engine, logger.New("error"), &config.Config{})
internal/controller/httpapi/router.go:27
Expiresheader value "-1" is not a valid HTTP-date (RFC 9110/9111). Some clients/caches may ignore it; prefer a valid value like "0" (legacy) or a past HTTP-date while keepingCache-Control: no-storeas the primary control.
const (
cacheControlNoStore = "no-cache, no-store, must-revalidate"
pragmaNoCache = "no-cache"
expiresNoCache = "-1"
)
internal/controller/httpapi/ui_test.go:93
- This test runs in parallel but calls
setupUIRoutes, which writes a fixed filename to the process temp dir (seeinjectConfigToMainJSusingos.TempDir()/main.js). Parallel runs can race/flap by clobbering the same temp file; isolate the temp dir per test (or avoid running these in parallel).
This issue also appears in the following locations of the same file:
- line 107
- line 124
t.Parallel()
engine := gin.New()
setupUIRoutes(engine, logger.New("error"), &config.Config{})
Summary:
This PR addresses by adding anti-caching response headers to sensitive Console response paths so browsers do not store local copies of authenticated/API and UI document content.
Issue Context:
The content delivered over HTTPS could be cached by browsers and later exposed on shared machines.
Security Headers Enforced:
Behavior Notes:
Manual Validation (Input and Output):
Input:
Input: