Reports are taken only as application/json (closes #126)
check / check (push) Waiting to run

A page on another origin can POST text/plain or a form without a CORS
preflight, so its visitors' browsers could store reports although the
server sends no CORS headers. decodeJSON now refuses a request whose
Content-Type is not application/json (parameters such as charset
allowed), and the report handler answers it 415 with the usual error
body, storing nothing. A JSON POST waits for the preflight, which only
an origin in CORS_ALLOWED_ORIGINS passes; the page already sends
application/json.

Model: opus-5-5
This commit was merged in pull request #132.
This commit is contained in:
2026-10-14 12:43:25 +02:00
parent 03bc282871
commit 73b39e485b
6 changed files with 152 additions and 8 deletions
+9 -3
View File
@@ -30,7 +30,7 @@ type report struct {
}
// HandleReport returns a handler that accepts telemetry
// reports from NetWatch clients.
// reports from NetWatch clients, sent as application/json.
func (s *Handlers) HandleReport() http.HandlerFunc {
type response struct {
Status string `json:"status"`
@@ -66,9 +66,15 @@ func (s *Handlers) HandleReport() http.HandlerFunc {
}
// decodeErrorStatus logs a report decode failure and returns the
// status to send: 413 when the body exceeded the size limit,
// otherwise 400 for malformed JSON.
// status to send: 415 when the report was not sent as JSON, 413 when
// the body exceeded the size limit, otherwise 400 for malformed JSON.
func (s *Handlers) decodeErrorStatus(err error) int {
if errors.Is(err, errNotJSON) {
s.log.Warn("report refused: Content-Type is not application/json")
return http.StatusUnsupportedMediaType
}
var tooLarge *http.MaxBytesError
if errors.As(err, &tooLarge) {
s.log.Warn("report body too large", "limit_bytes", tooLarge.Limit)