Files
3x-ui/internal/web/service/access_log_parse_test.go
T
MHSanaei 68a981c0c3 fix(server): guard access-log parser against malformed lines
GetXrayLogs split each Xray access-log line on whitespace and then read
fixed offsets — parts[1] for the timestamp and parts[i+1] after the "from",
"accepted" and "email:" markers — without checking the line had that many
fields. A truncated or malformed line (the logged destination is
attacker-influenced) indexed past the slice and panicked; the panel handler
returned a 500 via Gin's recovery.

Extract the per-line field parsing into parseAccessLogFields and length
guard every positional lookup so a short line yields a partial entry
instead of panicking.
2026-07-15 04:44:53 +02:00

50 lines
1.6 KiB
Go

package service
import "testing"
// Xray access-log lines carry attacker-influenced content (a client's requested
// destination is logged verbatim) and can be truncated. parseAccessLogFields
// must never panic on a short or malformed line, and must still parse a
// well-formed line correctly.
func TestParseAccessLogFields(t *testing.T) {
malformed := []string{
"",
"singletoken",
"2024/01/02",
"2024/01/02 15:04:05.000000 from",
"2024/01/02 15:04:05.000000 accepted",
"2024/01/02 15:04:05.000000 email:",
}
for _, line := range malformed {
func() {
defer func() {
if r := recover(); r != nil {
t.Errorf("parseAccessLogFields panicked on %q: %v", line, r)
}
}()
_ = parseAccessLogFields(line)
}()
}
line := "2024/01/02 15:04:05.123456 from 1.2.3.4:555 accepted tcp:example.com:443 [inbound-tag >> outbound-tag] email: alice@example.com"
entry := parseAccessLogFields(line)
if entry.FromAddress != "1.2.3.4:555" {
t.Errorf("FromAddress = %q, want %q", entry.FromAddress, "1.2.3.4:555")
}
if entry.ToAddress != "tcp:example.com:443" {
t.Errorf("ToAddress = %q, want %q", entry.ToAddress, "tcp:example.com:443")
}
if entry.Inbound != "inbound-tag" {
t.Errorf("Inbound = %q, want %q", entry.Inbound, "inbound-tag")
}
if entry.Outbound != "outbound-tag" {
t.Errorf("Outbound = %q, want %q", entry.Outbound, "outbound-tag")
}
if entry.Email != "alice@example.com" {
t.Errorf("Email = %q, want %q", entry.Email, "alice@example.com")
}
if entry.DateTime.IsZero() {
t.Error("DateTime was not parsed from a well-formed line")
}
}