Files
palette/internal/api/pentest_rawct_test.go
poslop 4f1e901f04
CI / test (push) Successful in 19s
CI / docker (push) Failing after 2m7s
Refactor: split monolith into cmd/palette + internal/{store,api,web,lang} (#35)
2026-09-09 01:33:39 -05:00

66 lines
2.1 KiB
Go

package api
import (
"net/http/httptest"
"strings"
"testing"
)
// #34: attacker-controlled content_type must not let a paste be served as
// HTML/SVG/XML from /raw (stored XSS). Only a fixed safe set passes through.
func TestRawRejectsHTMLContentType(t *testing.T) {
globalLimiter = newLimiter() // fresh rate-limit buckets
s := testServer(t)
h := s.routes()
for _, ct := range []string{
"text/html", "TEXT/HTML", "text/html;charset=utf-8", "text/html;x=1",
"application/xhtml+xml", "image/svg+xml", "text/html,",
} {
globalLimiter = newLimiter() // burst 5, loop makes 7 creates
body := `{"content":"<script>alert(1)</script>","content_type":"` + ct + `"}`
rec := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(body))
h.ServeHTTP(rec, req)
if rec.Code != 201 {
t.Fatalf("ct %q: create got %d: %s", ct, rec.Code, rec.Body.String())
}
id := jsonField(t, rec.Body.String(), "id")
rec = httptest.NewRecorder()
req = httptest.NewRequest("GET", "/raw/"+id, nil)
h.ServeHTTP(rec, req)
if got := rec.Header().Get("Content-Type"); got == ct {
t.Errorf("ct %q was served verbatim from /raw (stored XSS vector)", ct)
}
if got := rec.Header().Get("X-Content-Type-Options"); got != "nosniff" {
t.Errorf("ct %q: /raw missing X-Content-Type-Options: nosniff", ct)
}
}
}
func TestRawAllowsSafeContentType(t *testing.T) {
globalLimiter = newLimiter()
s := testServer(t)
h := s.routes()
for _, ct := range []string{"text/plain", "image/png", "application/pdf", "application/octet-stream"} {
globalLimiter = newLimiter()
body := `{"content":"hi","content_type":"` + ct + `"}`
rec := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(body))
h.ServeHTTP(rec, req)
if rec.Code != 201 {
t.Fatalf("ct %q: create got %d", ct, rec.Code)
}
id := jsonField(t, rec.Body.String(), "id")
rec = httptest.NewRecorder()
req = httptest.NewRequest("GET", "/raw/"+id, nil)
h.ServeHTTP(rec, req)
if got := rec.Header().Get("Content-Type"); got != ct {
t.Errorf("ct %q: got %q", ct, got)
}
}
}