aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_players.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/api_players.go')
-rw-r--r--internal/admin/api_players.go18
1 files changed, 17 insertions, 1 deletions
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/<name>.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
}