From 67e01aab85607b9e601185c7d62dff576af3bb43 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 15:42:23 -0400 Subject: fix: close map OOM, admin traversal, transport safespot, room rekey, and legacy payout recovery --- internal/admin/api_players.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'internal/admin/api_players.go') diff --git a/internal/admin/api_players.go b/internal/admin/api_players.go index 66142c5..8ac0dd2 100644 --- a/internal/admin/api_players.go +++ b/internal/admin/api_players.go @@ -87,7 +87,23 @@ func (s *AdminServer) handlePlayerByID(w http.ResponseWriter, r *http.Request) { } if strings.HasPrefix(path, "account/") { - s.getAccount(w, strings.TrimPrefix(path, "account/")) + acct := strings.TrimPrefix(path, "account/") + if err := player.ValidName(acct); err != nil { + http.Error(w, `{"error":"invalid account id"}`, http.StatusBadRequest) + return + } + s.getAccount(w, acct) + return + } + + // Validate before the first join into players/characters/.yaml. + // ServeMux cleans the ESCAPED path but handlers read the DECODED + // r.URL.Path, so a percent-encoded segment like %2e%2e%2f reaches this + // handler as "../" and would otherwise escape the data dir (and bypass + // the password_hash redaction in getAccount). ValidName is the same + // invariant every other name join in the codebase enforces. + if err := player.ValidName(path); err != nil { + http.Error(w, `{"error":"invalid player id"}`, http.StatusBadRequest) return } -- cgit v1.2.3