Summary
The kanidmd web UI renders the WebAuthn passkey-registration challenge as raw JSON inside an inline <script id="data"> element using the Askama |safe filter. The challenge embeds the account's displayname, which serde_json serialises without escaping </>. A displayname containing </script> therefore terminates the script element early and injects arbitrary HTML into the credential-update page. Because the page is htmx-driven and the server's CSP allows 'unsafe-eval', injected hx-* attributes can issue authenticated same-origin API requests with the viewer's bearer cookie.
Impact
An authenticated attacker who is a member of idm_people_admins can write the displayname of any Person entry — including high-privilege persons — because idm_acp_people_pii_manage carries no high-privilege exclusion filter. When the targeted high-privilege user later opens Add Passkey on their own credential-update page (/ui/reset), the injected markup is swapped into the DOM and htmx fires attacker-chosen same-origin requests authenticated as the victim. This allows a helpdesk-tier operator to escalate to idm_admins (e.g. by POSTing themselves into the group) or otherwise act with the victim's session. The self-write path (idm_people_self_name_write) is self-XSS only and is not counted toward impact. Even without the htmx vector, the breakout permits <meta http-equiv='refresh'> open-redirect and arbitrary defacement of the credential page.
Details
Affected versions
All releases shipping the htmx credential-update views
References
Summary
The kanidmd web UI renders the WebAuthn passkey-registration challenge as raw JSON inside an inline
<script id="data">element using the Askama|safefilter. The challenge embeds the account'sdisplayname, whichserde_jsonserialises without escaping</>. Adisplaynamecontaining</script>therefore terminates the script element early and injects arbitrary HTML into the credential-update page. Because the page is htmx-driven and the server's CSP allows'unsafe-eval', injectedhx-*attributes can issue authenticated same-origin API requests with the viewer's bearer cookie.Impact
An authenticated attacker who is a member of
idm_people_adminscan write thedisplaynameof anyPersonentry — including high-privilege persons — becauseidm_acp_people_pii_managecarries no high-privilege exclusion filter. When the targeted high-privilege user later opens Add Passkey on their own credential-update page (/ui/reset), the injected markup is swapped into the DOM and htmx fires attacker-chosen same-origin requests authenticated as the victim. This allows a helpdesk-tier operator to escalate toidm_admins(e.g. by POSTing themselves into the group) or otherwise act with the victim's session. The self-write path (idm_people_self_name_write) is self-XSS only and is not counted toward impact. Even without the htmx vector, the breakout permits<meta http-equiv='refresh'>open-redirect and arbitrary defacement of the credential page.Details
|safesinkserde_json::to_stringof the challengedisplaynameflows intostart_passkey_registrationAffected versions
All releases shipping the htmx credential-update views
References