Severity by source
AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
The client-side escapeForHtml() function in KimaiEscape.js, introduced in commit 89bfa82c (#2959) to fix a JavaScript XSS vulnerability, only escapes <, >, and & but does not escape " (double quote) or ' (single quote). When user-controlled data (profile alias) is placed in an HTML attribute context (title="__DISPLAY__") via the team member form prototype and rendered through innerHTML, the missing quote escaping allows HTML attribute injection, resulting in Stored XSS.
Details
Incomplete security patch. The escapeForHtml() function was meant to prevent XSS but missed quote characters, which are critical for HTML attribute context escaping.
Vulnerable code - assets/js/plugins/KimaiEscape.js:29-33:
const tagsToReplace = {
'&': '&',
'<': '<',
'>': '>',
// MISSING: '"': '"'
// MISSING: "'": '''
};Affected code files:
assets/js/plugins/KimaiEscape.js:24-38- incomplete escape functionassets/js/forms/KimaiTeamForm.js:77,86- replacement + innerHTMLtemplates/macros/widgets.html.twig:126-title="{{ tooltip }}"in avatar macrotemplates/form/blocks.html.twig:104-{{ widgets.avatar('__INITIALS__', '__COLOR__', '__DISPLAY__') }}
PoC
Please extract the uploaded compressed file before proceeding
- ./setup.sh
- ./poc_xss.sh
<img width="751" height="155" alt="스크린샷 2026-04-07 오후 9 06 27" src="https://github.com/user-attachments/assets/c09a23fb-f60b-49dd-9018-8c723e35b4c4" />
Impact
- Stored XSS: payload persists in the database (user alias field)
- Privilege escalation: ROLE_USER injects XSS that executes in ROLE_ADMIN/ROLE_SUPER_ADMIN browser session
Analysis
Summary
The client-side escapeForHtml() function in KimaiEscape.js, introduced in commit 89bfa82c (#2959) to fix a JavaScript XSS vulnerability, only escapes <, >, and & but does not escape " (double quote) or ' (single quote). When user-controlled data (profile alias) is placed in an HTML attribute context (title="__DISPLAY__") via the team member form prototype and rendered through innerHTML, the missing quote escaping allows HTML attribute injection, resulting in Stored XSS.
Details
Incomplete security patch. The escapeForHtml() function was meant to prevent XSS but missed quote characters, which are critical for HTML attribute context escaping.
Vulnerable code - assets/js/plugins/KimaiEscape.js:29-33:
const tagsToReplace = {
'&': '&',
'<': '<',
'>': '>',
// MISSING: '"': '"'
// MISSING: "'": '''
};Affected code files:
assets/js/plugins/KimaiEscape.js:24-38- incomplete escape functionassets/js/forms/KimaiTeamForm.js:77,86- replacement + innerHTMLtemplates/macros/widgets.html.twig:126-title="{{ tooltip }}"in avatar macrotemplates/form/blocks.html.twig:104-{{ widgets.avatar('__INITIALS__', '__COLOR__', '__DISPLAY__') }}
PoC
Please extract the uploaded compressed file before proceeding
- ./setup.sh
- ./poc_xss.sh
<img width="751" height="155" alt="스크린샷 2026-04-07 오후 9 06 27" src="https://github.com/user-attachments/assets/c09a23fb-f60b-49dd-9018-8c723e35b4c4" />
Impact
- Stored XSS: payload persists in the database (user alias field)
- Privilege escalation: ROLE_USER injects XSS that executes in ROLE_ADMIN/ROLE_SUPER_ADMIN browser session
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-23575
GHSA-g82g-m9vx-vhjg