Added panic mode protections to make the server more secure

This commit is contained in:
2025-08-22 18:54:10 -04:00
parent 5067913c21
commit 5dfc710ae9
7 changed files with 430 additions and 247 deletions

View File

@@ -1,4 +1,3 @@
// cmd/shard/main.go
package main
import (
@@ -26,8 +25,9 @@ func getenvBool(key string, def bool) bool {
}
func staticHeaders(next http.Handler) http.Handler {
onion := os.Getenv("GC_ONION_LOCATION") // optional: e.g., http://xxxxxxxx.onion/
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Security headers
// Security headers + strict CSP (no inline) + COEP
w.Header().Set("Referrer-Policy", "no-referrer")
w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
w.Header().Set("Cross-Origin-Resource-Policy", "same-site")
@@ -35,6 +35,19 @@ func staticHeaders(next http.Handler) http.Handler {
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Strict-Transport-Security", "max-age=15552000; includeSubDomains; preload")
w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
// Allow only self + HTTPS for fetch/SSE; no inline styles/scripts
w.Header().Set("Content-Security-Policy",
"default-src 'self'; "+
"script-src 'self'; "+
"style-src 'self'; "+
"img-src 'self' data:; "+
"connect-src 'self' https:; "+
"frame-ancestors 'none'; object-src 'none'; base-uri 'none'; form-action 'self'; "+
"require-trusted-types-for 'script'")
if onion != "" {
w.Header().Set("Onion-Location", onion)
}
// Basic CORS for static (GET only effectively)
w.Header().Set("Access-Control-Allow-Origin", "*")
@@ -72,12 +85,17 @@ func main() {
dataDir = "/var/lib/greencoast"
}
coarseTS := getenvBool("GC_COARSE_TS", false)
coarseTS := getenvBool("GC_COARSE_TS", true) // safer default (less precise metadata)
zeroTrust := getenvBool("GC_ZERO_TRUST", true)
encRequired := getenvBool("GC_ENCRYPTION_REQUIRED", true) // operator-blind by default
requirePOP := getenvBool("GC_REQUIRE_POP", true) // for logging only; API defaults to true internally
requirePOP := getenvBool("GC_REQUIRE_POP", true) // logged only here
signingSecretHex := os.Getenv("GC_SIGNING_SECRET_HEX")
if len(signingSecretHex) < 64 {
log.Printf("WARN: GC_SIGNING_SECRET_HEX length=%d (need >=64 hex chars)", len(signingSecretHex))
} else {
log.Printf("GC_SIGNING_SECRET_HEX OK (len=%d)", len(signingSecretHex))
}
discID := os.Getenv("GC_DISCORD_CLIENT_ID")
discSecret := os.Getenv("GC_DISCORD_CLIENT_SECRET")
@@ -90,13 +108,17 @@ func main() {
}
ix := index.New()
// Reindex on boot from whatever files exist on disk
// Reindex on boot from existing files (coarse time if enabled)
if err := store.Walk(func(hash string, size int64, mod time.Time) error {
when := mod.UTC()
if coarseTS {
when = when.Truncate(time.Minute)
}
return ix.Put(index.Entry{
Hash: hash,
Bytes: size,
StoredAt: mod.UTC().Format(time.RFC3339Nano),
Private: false, // unknown here; safe default
StoredAt: when.Format(time.RFC3339Nano),
Private: false, // unknown here
})
}); err != nil {
log.Printf("reindex on boot: %v", err)