security: escape user input in 403 error response to prevent XSS

The require_auth decorator was interpolating user['username'] and the
allowed_groups list directly into HTML strings. An attacker with a
crafted username or control over group names could inject arbitrary HTML.

Use html.escape() on both values before insertion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 23:41:31 -04:00
parent c0e59cfa9e
commit d8339e8eb6
+5 -2
View File
@@ -5,6 +5,7 @@ management UI. Authentication via Authelia forward-auth headers.
All monitoring and alerting is handled by the separate monitor.py daemon. All monitoring and alerting is handled by the separate monitor.py daemon.
""" """
import hashlib import hashlib
import html
import ipaddress import ipaddress
import json import json
import logging import logging
@@ -132,10 +133,12 @@ def require_auth(f):
) )
allowed = _config().get('auth', {}).get('allowed_groups', ['admin']) allowed = _config().get('auth', {}).get('allowed_groups', ['admin'])
if not any(g in allowed for g in user['groups']): if not any(g in allowed for g in user['groups']):
safe_user = html.escape(user['username'])
safe_groups = html.escape(', '.join(allowed))
return ( return (
f'<h1>403 Access denied</h1>' f'<h1>403 Access denied</h1>'
f'<p>Your account ({user["username"]}) is not in an allowed group ' f'<p>Your account ({safe_user}) is not in an allowed group '
f'({", ".join(allowed)}).</p>', f'({safe_groups}).</p>',
403, 403,
) )
return f(*args, **kwargs) return f(*args, **kwargs)