66 lines
2.1 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|