fix(server): XSS, missing score submission, leaderboard never updated, no LIMIT
Build and Deploy / build-and-push (push) Successful in 4m14s
Build and Deploy / build-and-push (push) Successful in 4m14s
- leaderboard.html, replays.html: escape user-supplied display_name and username before inserting into innerHTML to prevent stored XSS - game.js: call POST /api/replays on win so browser-game completions are recorded; scores were never submitted before this fix - replays.rs: after replay insert, upsert leaderboard best_score / best_time_secs for opted-in users when the new score beats their current best (classic mode only); scores were never updated before this fix - leaderboard.rs: add LIMIT 100 to GET /api/leaderboard to prevent unbounded query growth Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -54,7 +54,8 @@ pub async fn get_leaderboard(
|
||||
CASE WHEN l.best_score IS NULL THEN 1 ELSE 0 END ASC,
|
||||
l.best_score DESC,
|
||||
CASE WHEN l.best_time_secs IS NULL THEN 1 ELSE 0 END ASC,
|
||||
l.best_time_secs ASC"#
|
||||
l.best_time_secs ASC
|
||||
LIMIT 100"#
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
@@ -114,6 +114,32 @@ pub async fn upload(
|
||||
.execute(&state.pool)
|
||||
.await?;
|
||||
|
||||
// Update leaderboard best score/time for opted-in users when this replay
|
||||
// beats their existing best. Only classic mode counts for the leaderboard.
|
||||
if header.mode == "classic" {
|
||||
sqlx::query!(
|
||||
r#"UPDATE leaderboard
|
||||
SET best_score = ?,
|
||||
best_time_secs = ?,
|
||||
recorded_at = ?
|
||||
WHERE user_id = ?
|
||||
AND (
|
||||
best_score IS NULL
|
||||
OR ? > best_score
|
||||
OR (? = best_score AND (best_time_secs IS NULL OR ? < best_time_secs))
|
||||
)"#,
|
||||
header.final_score,
|
||||
header.time_seconds,
|
||||
header.recorded_at,
|
||||
user.user_id,
|
||||
header.final_score,
|
||||
header.final_score,
|
||||
header.time_seconds,
|
||||
)
|
||||
.execute(&state.pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(Json(ReplayUploadResponse { id }))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user