Code sync, security fixes
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// assetHandler mirrors how the router mounts the embedded assets: the request
|
||||
// path has "/static/" stripped, and the file system is expected to be rooted at
|
||||
// the assets themselves.
|
||||
func assetHandler() http.Handler {
|
||||
return http.StripPrefix("/static/", http.FileServerFS(StaticFS()))
|
||||
}
|
||||
|
||||
// Static assets must actually be served. A 404 here does not look like a
|
||||
// missing file in the browser: the 404 body arrives as text/plain under
|
||||
// X-Content-Type-Options: nosniff, so the browser refuses it and reports
|
||||
// corrupted content, which sends you looking for an encoding bug instead.
|
||||
func TestStaticAssetsAreServed(t *testing.T) {
|
||||
h := assetHandler()
|
||||
|
||||
for _, asset := range []struct{ path, wantType string }{
|
||||
{"/static/app.css", "text/css"},
|
||||
{"/static/public.css", "text/css"},
|
||||
{"/static/app.js", "javascript"},
|
||||
{"/static/favicon.svg", "image/svg+xml"},
|
||||
} {
|
||||
t.Run(asset.path, func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, asset.path, nil))
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200 — the asset is not reachable at the path "+
|
||||
"the templates reference", w.Code)
|
||||
}
|
||||
if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, asset.wantType) {
|
||||
t.Fatalf("Content-Type = %q, want something containing %q", ct, asset.wantType)
|
||||
}
|
||||
if w.Body.Len() == 0 {
|
||||
t.Fatal("the asset is empty")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Path traversal must not escape the asset root.
|
||||
func TestStaticAssetsRefuseTraversal(t *testing.T) {
|
||||
h := assetHandler()
|
||||
for _, p := range []string{
|
||||
"/static/../render.go",
|
||||
"/static/../../go.mod",
|
||||
"/static/..%2f..%2fgo.mod",
|
||||
} {
|
||||
w := httptest.NewRecorder()
|
||||
h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, p, nil))
|
||||
if w.Code == http.StatusOK {
|
||||
t.Errorf("%s was served with 200; it must not escape the asset root", p)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user