Code review fixes: - 🟡 #1: Replace python3 with jq in Dockerfile template stages (~50MB → ~2MB) - 🟡 #2: Add clone count verification to scripts/clone-manifest.sh (set -e + expected vs actual count check — fails build if any clone fails) - 🟡 #3: Drop 'unsafe-eval' from CSP (not needed for Next.js production standalone builds, only dev mode). Updated test assertion. - 🟡 #4: Remove broken pyproject.toml from workspace-template/ (it claimed to package as molecule-ai-workspace-runtime but the directory structure didn't match — the real package ships from the standalone repo) - 🔵 #1: Add version-pinning TODO comment to manifest.json - 🔵 #3: Add full repo URLs + test counts for SDK/MCP/CLI/runtime in CLAUDE.md Security (GitGuardian alert): - Removed Telegram bot token (8633739353:AA...) from template-molecule-dev pm/.env — replaced with ${TELEGRAM_BOT_TOKEN} placeholder - Removed Claude OAuth token (sk-ant-oat01-...) from template-molecule-dev root .env — replaced with ${CLAUDE_CODE_OAUTH_TOKEN} placeholder - Both tokens need immediate rotation by the operator Tests: Platform middleware tests updated + all pass.
53 lines
2.6 KiB
Go
53 lines
2.6 KiB
Go
package middleware
|
|
|
|
import "github.com/gin-gonic/gin"
|
|
|
|
// SecurityHeaders returns a Gin middleware that sets standard HTTP security
|
|
// headers on every response to mitigate common web-application attacks:
|
|
//
|
|
// - X-Content-Type-Options: nosniff — prevents MIME-type sniffing
|
|
// - X-Frame-Options: DENY — blocks iframe embedding (clickjacking)
|
|
// - Content-Security-Policy: default-src 'self' — restricts resource loading to same origin
|
|
// - Strict-Transport-Security: max-age=31536000; includeSubDomains — enforces HTTPS for 1 year
|
|
// - Referrer-Policy: strict-origin-when-cross-origin — avoids leaking full paths/queries in Referer
|
|
// - Permissions-Policy: camera=(), microphone=(), geolocation=() — denies sensor access for embedded content
|
|
func SecurityHeaders() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
c.Header("X-Content-Type-Options", "nosniff")
|
|
c.Header("X-Frame-Options", "DENY")
|
|
c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
|
// #282: these two were documented in CLAUDE.md but missing from
|
|
// the middleware. Referrer-Policy prevents browsers from leaking
|
|
// the full Referer URL to cross-origin resources (which can
|
|
// expose internal paths/queries). Permissions-Policy denies
|
|
// sensor access by default — especially relevant because the
|
|
// canvas embeds iframes for Langfuse traces.
|
|
c.Header("Referrer-Policy", "strict-origin-when-cross-origin")
|
|
c.Header("Permissions-Policy", "camera=(), microphone=(), geolocation=()")
|
|
|
|
// CSP: only apply to API responses. Canvas-proxied routes
|
|
// (NoRoute → reverse-proxy to Next.js) serve HTML with inline
|
|
// scripts + styles that `default-src 'self'` blocks. Next.js
|
|
// sets its own CSP via <meta> tags. The Go middleware should
|
|
// not override it for proxied HTML responses.
|
|
//
|
|
// Detection: API routes are registered explicitly in the router;
|
|
// canvas-proxied routes hit NoRoute. We can't detect NoRoute
|
|
// before c.Next() fires, so instead we check the response
|
|
// Content-Type after Next() — but that's too late for headers.
|
|
//
|
|
// Simpler: apply a permissive CSP that allows Next.js to work.
|
|
// 'unsafe-inline' is needed for Next.js standalone builds that
|
|
// inject inline scripts for hydration. 'unsafe-eval' was dropped
|
|
// after confirming production canvas renders without it.
|
|
c.Header("Content-Security-Policy",
|
|
"default-src 'self'; "+
|
|
"script-src 'self' 'unsafe-inline'; "+
|
|
"style-src 'self' 'unsafe-inline'; "+
|
|
"img-src 'self' data: blob:; "+
|
|
"connect-src 'self' ws: wss:; "+
|
|
"font-src 'self' data:")
|
|
c.Next()
|
|
}
|
|
}
|