Initial commit
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Assisted-by: GLM 5.3
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
|
||||
package web
|
||||
|
||||
import (
|
||||
"encoding/json/v2"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CrossOrigin refuses a state-changing request that a browser sent from
|
||||
// another origin, using the standard library's Fetch Metadata check:
|
||||
// Sec-Fetch-Site when the browser sends it, and the Origin header against
|
||||
// the Host header otherwise.
|
||||
//
|
||||
// It is the outer gate, and the admin's per-session CSRF token is the
|
||||
// inner one, because the two cover different cases: this refuses a
|
||||
// cross-site request before any handler runs, and the token also refuses
|
||||
// a same-site request (another port on the same host) and a browser that
|
||||
// sends neither header, which this check deliberately allows as a
|
||||
// non-browser client.
|
||||
func CrossOrigin() func(http.Handler) http.Handler {
|
||||
protection := http.NewCrossOriginProtection()
|
||||
protection.SetDenyHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
slog.Warn("web: refused a cross-origin request",
|
||||
"method", r.Method, "path", r.URL.Path, "origin", r.Header.Get("Origin"))
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
_ = json.MarshalWrite(w, map[string]any{"error": "cross_origin"}, json.Deterministic(true))
|
||||
}))
|
||||
return protection.Handler
|
||||
}
|
||||
Reference in New Issue
Block a user