Skip to content

Commit 5f00c34

Browse files
authored
test(AtomicLevel): demonstrate Handler is not vulnerable to XSS (#1477)
Adds a unit test and a fuzz test to demonstrate that the AtomicLevel handler is not vulnerable to XSS. I ran the fuzz test on my computer for 10 minutes on my laptop with no cases where `<...>` was present in the response body. ``` ... fuzz: elapsed: 9m57s, execs: 43145040 (95839/sec), new interesting: 442 (total: 445) fuzz: elapsed: 10m0s, execs: 43396113 (83690/sec), new interesting: 442 (total: 445) ``` Refs #1476
1 parent 9669253 commit 5f00c34

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

http_handler_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ package zap_test
2323
import (
2424
"encoding/json"
2525
"errors"
26+
"io"
2627
"net/http"
2728
"net/http/httptest"
2829
"strings"
@@ -215,3 +216,44 @@ type brokenHTTPResponseWriter struct {
215216
func (w *brokenHTTPResponseWriter) Write([]byte) (int, error) {
216217
return 0, errors.New("great sadness")
217218
}
219+
220+
func TestAtomicLevelServeHTTPBadLevel(t *testing.T) {
221+
srv := httptest.NewServer(zap.NewAtomicLevel())
222+
defer srv.Close()
223+
224+
req, err := http.NewRequest(http.MethodPut, srv.URL, strings.NewReader(`{"level":"<script>alert(\"malicious\")</script>"}`))
225+
require.NoError(t, err, "Error constructing request.")
226+
227+
res, err := http.DefaultClient.Do(req)
228+
require.NoError(t, err, "Error making request.")
229+
defer func() {
230+
assert.NoError(t, res.Body.Close(), "Error closing response body.")
231+
}()
232+
233+
assert.Equal(t, http.StatusBadRequest, res.StatusCode, "Unexpected status code.")
234+
resBody, err := io.ReadAll(res.Body)
235+
require.NoError(t, err, "Error reading response body.")
236+
237+
assert.Contains(t, string(resBody), "unrecognized level", "Unexpected error message.")
238+
assert.NotContains(t, string(resBody), "<script>", "Unexpected error message.")
239+
}
240+
241+
func FuzzAtomicLevelServeHTTP(f *testing.F) {
242+
f.Add(`{"level":"info"}`)
243+
f.Add(`{"level":"warn"}`)
244+
f.Add(`{"level":"<script>alert(\"malicious\")</script>"}`)
245+
f.Fuzz(func(t *testing.T, input string) {
246+
lvl := zap.NewAtomicLevel()
247+
248+
resw := httptest.NewRecorder()
249+
req, err := http.NewRequest(http.MethodPut, "http://localhost:9999/log/level", strings.NewReader(input))
250+
require.NoError(t, err, "Error constructing request.")
251+
252+
lvl.ServeHTTP(resw, req)
253+
254+
require.NotEqual(t, http.StatusInternalServerError, resw.Code, "Unexpected status code.")
255+
256+
// Response body must never contain HTML tags.
257+
assert.NotRegexp(t, `<[^>]+>`, resw.Body.String(), "Unexpected HTML tag in response body.")
258+
})
259+
}

0 commit comments

Comments
 (0)