mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-18 14:51:26 +02:00
The client trusted the server to pre-escape chat content and rendered user-supplied fields via .html()/innerHTML — one server regression away from stored XSS, and the admin panel injected user-controlled payout addresses into its authenticated DOM. - Add a single shared escapeHtml helper (escapes all five HTML-significant chars including both quotes); leaderboard now delegates to it. - Escape chat username + message in onChatBroadcast/onChatHistory. - Escape user-controlled fields in the admin panel (payout address, socket id, player name, status) and make its local escapeHtml quote-safe so values in title="..." can't break out. - Add CSP plus X-Content-Type-Options, X-Frame-Options and Referrer-Policy headers via middleware. connect-src 'self' keeps Socket.IO working; removing 'unsafe-inline' (nonces) is tracked as a later cleanup. Full suite: 13 suites / 119 tests.
19 lines
752 B
JavaScript
19 lines
752 B
JavaScript
/**
|
|
* Shared HTML-escaping helper — the single source of truth for escaping untrusted
|
|
* (server- or user-supplied) text before it is inserted into innerHTML / jQuery .html().
|
|
* Escapes all five HTML-significant characters, including both quote types so the
|
|
* result is safe in both element text and quoted attribute values.
|
|
*/
|
|
(function (global) {
|
|
function escapeHtml(value) {
|
|
if (value === null || value === undefined) return '';
|
|
return String(value)
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''');
|
|
}
|
|
global.escapeHtml = escapeHtml;
|
|
})(typeof window !== 'undefined' ? window : this);
|