fix(auth): sanitize email addresses

Previously, maliciously crafted email addresses
could be used to sneak HTML code into the HedgeDoc
editor, since HedgeDoc uses the local part of the
address as a display name for users.
We're now sanitizing this using DOMPurify.

Co-authored-by: Philip Molares <philip.molares@udo.edu>
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson
2026-06-17 22:35:16 +02:00
parent 291b9d592d
commit dd40a6c04b
3 changed files with 13 additions and 5 deletions

View File

@@ -143,10 +143,11 @@ module.exports = function (sequelize, DataTypes) {
return filterXSS(photo) return filterXSS(photo)
} }
User.parseProfileByEmail = function (email) { User.parseProfileByEmail = function (email) {
const sanitizedEmail = email.replaceAll('"', '').replaceAll("'", '').replaceAll('<', '').replaceAll('>', '')
return { return {
name: email.substring(0, email.lastIndexOf('@')), name: sanitizedEmail.split('@')[0],
photo: generateAvatarURL('', email, false), photo: generateAvatarURL('', sanitizedEmail, false),
biggerphoto: generateAvatarURL('', email, true) biggerphoto: generateAvatarURL('', sanitizedEmail, true)
} }
} }

View File

@@ -2,6 +2,13 @@
## <i class="fa fa-tag"></i> 1.x <i class="fa fa-calendar-o"></i> UNRELEASED ## <i class="fa fa-tag"></i> 1.x <i class="fa fa-calendar-o"></i> UNRELEASED
### Security fixes
This release contains a ... security fix:
- [GHSA-6c2w-8w96-3pcv](https://github.com/hedgedoc/hedgedoc/security/advisories/GHSA-6c2w-8w96-3pcv) reports a possible HTML injection via the localpart of an email address.
Thanks to [Chandler Johnson](https://github.com/chndlrx) for reporting!
### Enhancements ### Enhancements
- Added a warning page when clicking external links - Added a warning page when clicking external links

View File

@@ -34,7 +34,7 @@
<small> <small>
<span> <span>
<% if(lastchangeuserprofile) { %> <% if(lastchangeuserprofile) { %>
<span class="ui-lastchangeuser">&thinsp;<i class="ui-user-icon small" style="background-image: url(<%- lastchangeuserprofile.photo %>);" data-toggle="tooltip" data-placement="right" title="<%- lastchangeuserprofile.name %>"></i></span> <span class="ui-lastchangeuser">&thinsp;<i class="ui-user-icon small" style="background-image: url(<%- lastchangeuserprofile.photo %>);" data-toggle="tooltip" data-placement="right" title="<%= lastchangeuserprofile.name %>"></i></span>
<% } else { %> <% } else { %>
<span class="ui-no-lastchangeuser">&thinsp;<i class="fa fa-clock-o fa-fw" style="width: 18px;"></i></span> <span class="ui-no-lastchangeuser">&thinsp;<i class="fa fa-clock-o fa-fw" style="width: 18px;"></i></span>
<% } %> <% } %>
@@ -45,7 +45,7 @@
<br> <br>
<% if(ownerprofile && owner !== lastchangeuser) { %> <% if(ownerprofile && owner !== lastchangeuser) { %>
<span class="ui-owner"> <span class="ui-owner">
&thinsp;<i class="ui-user-icon small" style="background-image: url(<%- ownerprofile.photo %>);" data-toggle="tooltip" data-placement="right" title="<%- ownerprofile.name %>"></i> &thinsp;<i class="ui-user-icon small" style="background-image: url(<%- ownerprofile.photo %>);" data-toggle="tooltip" data-placement="right" title="<%= ownerprofile.name %>"></i>
&nbsp;<span class="text-uppercase">owned this note</span> &nbsp;<span class="text-uppercase">owned this note</span>
</span> </span>
<% } %> <% } %>