Ampersand in groups and subgroups name
Summary
Groups and subgroups created before GitLab 16.11 that contain ampersands in their names now display the HTML entity code & instead of rendering the ampersand character & properly.
Steps to reproduce
- Have a group created before GitLab 16.11 with an ampersand in the name (e.g., "R&D Team")
- Upgrade GitLab to version 17.5 or later
- View the group name in the GitLab UI
- Observe that
&displays as&
Note: New groups cannot be created with ampersands - validation now prevents this. This issue only affects legacy groups.
What is the current bug behavior?
Group names containing ampersands display the HTML entity & instead of the actual & character:
This is a cosmetic issue with no functional impact - the groups work correctly, but the display is incorrect.
What is the expected correct behavior?
Legacy group names containing ampersands should display the & character properly, just as they did in GitLab 16.11 and earlier versions.
Relevant logs and/or screenshots
See screenshot above showing & displaying literally instead of being rendered as &.
Implementation Guide for Contributors
Problem: HTML entities in group names are being double-escaped or not decoded properly during display.
Files to investigate:
app/views/groups/_group.html.haml(group display partials)app/helpers/groups_helper.rb(name rendering methods)- Vue components displaying group names in
app/assets/javascripts/groups/ - API serializers returning group names
Likely causes:
- Group name is already HTML-escaped in the database (stored as
&) - Display code is applying additional escaping via
h()orhtml_escape - Double-escaping:
&→&(in DB) →&(displayed as&)
Changes needed:
- Identify where
group.namerendering applies HTML escaping - Check if names in database are already escaped (query a legacy group)
- If already escaped in DB: Use
.html_safecarefully or decode before display - If not escaped in DB: Ensure proper single-pass escaping
- Consider using
sanitize()with a whitelist (likely empty for names)
Critical security consideration:
- Must maintain XSS protection while fixing display
- Test with malicious input:
<script>alert(1)</script>,<img src=x onerror=alert(1)> - Ensure fix doesn't enable script injection
- Consult security team before merging if uncertain
Testing approach:
- Create test fixtures with groups named:
R&D,Sales & Marketing,Q&A - Verify correct display in: group headers, breadcrumbs, dropdowns, admin lists, API responses
- Test XSS protection still works with dangerous characters
- Test both Haml templates and Vue.js components
- Verify behavior on both legacy groups and newly created groups (if validation is removed)
Areas to test:
- Group navigation sidebar
- Group settings pages
- Breadcrumb navigation
- Admin area group lists
- API endpoints returning group data
- Group selection dropdowns
Possible fixes
This is likely a double-escaping issue introduced during an upgrade. Check where group names are being HTML-escaped during rendering and ensure it only happens once. The name may already be escaped in the database for legacy groups.