Files
Felis/cmd/felis/nano_test.go
T
flyemoji fa3eda5228 fix(nano): quote and cap the request log line
felis nano logged every request with the raw RequestURI and %s. That
text is the caller's: a right-to-left override reordered the line as
displayed, an invalid UTF-8 byte made journald store the entry as a
binary blob that journalctl -f shows as "[N blob data]", and a query
near net/http's one-megabyte limit became a one-megabyte log line.

The URI is now capped at 256 bytes, several times a real hasJoined
query, and printed with %q, so control, bidi and invalid bytes appear
escaped. The handler assembly moved into nanoHandler so the logged
handler can be tested on its own; cmdNano serves it unchanged.

The new test sends a query carrying U+202E, a 0x9b byte and 4 KiB of
padding, and expects a valid UTF-8 line with the override escaped and
no more than twice the cap. Restoring the old unquoted line fails it.
2026-09-22 13:27:28 +09:00

36 lines
1.2 KiB
Go

package main
import (
"bytes"
"net/http"
"net/http/httptest"
"strconv"
"strings"
"testing"
"unicode/utf8"
)
// The request log prints text the caller chose. A bidi override must not reorder the line,
// an invalid byte must not make journald store the entry as a blob, and a huge query must
// not become a huge log line. serverId is left out so the handler answers without asking
// any source.
func TestNanoRequestLogIsQuotedAndCapped(t *testing.T) {
const rlo = rune(0x202e) // RIGHT-TO-LEFT OVERRIDE
var log bytes.Buffer
h := nanoHandler(nil, &log)
target := "/session/minecraft/hasJoined?username=" + string(rlo) + "evil" + string([]byte{0x9b}) + "31m" + strings.Repeat("a", 4096)
w := httptest.NewRecorder()
h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, target, nil))
line := log.String()
if strings.ContainsRune(line, rlo) || !utf8.ValidString(line) {
t.Fatalf("raw caller bytes reached the log: %q", line)
}
if escaped := strings.Trim(strconv.QuoteRune(rlo), "'"); !strings.Contains(line, escaped) {
t.Fatalf("log line %q should show the override escaped as %s", line, escaped)
}
if len(line) > 2*nanoLogURIMax {
t.Fatalf("log line is %d bytes for a %d-byte URI; want it capped", len(line), len(target))
}
}