HTML injection in Merge request title when deleting an MR, allows attacker to leak IPs and pop authentication dialog

⚠️ Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #3379381 by joaxcar on 2025-10-10, assigned to @katwu:

Report | Attachments | How To Reproduce

HackerOne Analyst Summary

Summary

The researcher was able to identify an HTML injection vulnerability in GitLab's merge request deletion functionality that allows malicious HTML content to be rendered through the v-safe-html component. When a merge request title contains HTML payloads, the content is properly sanitized in most areas of the application. However, when a user attempts to delete a merge request, the title is rendered in the deletion confirmation dialog without proper sanitization, allowing the HTML to execute.

The vulnerability can be exploited by creating merge requests with malicious HTML payloads in the title, such as <img src="https://gittlab.com/auth/test.svg">. When victims attempt to delete these merge requests, the HTML content is rendered in the deletion dialog. The attack can be enhanced by serving images from attacker-controlled domains with Link headers pointing to basic authentication-protected resources, which triggers authentication dialogs that appear to originate from gitlab.com but actually send credentials to the attacker's domain.

Steps to Reproduce

  1. Log in to GitLab and navigate to any project you own

Screenshot_2025-10-11_at_10.31.15.png

  1. Create a new Merge request

Screenshot_2025-10-11_at_10.31.29.pngScreenshot_2025-10-11_at_10.32.14.png

  1. Set the merge request title to: <img src="https://gittlab.com/auth/test.svg">

Screenshot_2025-10-11_at_10.32.30.png

  1. Navigate to the created merge request
  2. Click the Edit button on the merge request
  3. Scroll to the bottom of the edit page to locate the Delete button
  4. Click the Delete button to attempt deletion of the merge request

Screenshot_2025-10-11_at_10.33.30.png

  1. Observe that the deletion confirmation dialog renders the HTML image tag
  2. The image loads from the attacker's domain gittlab.com (note the typosquatting)
  3. If the attacker's server responds with a Link header like Link: <https://gittlab.com/auth/test>; rel=preload; as=track; fetchpriority="high" pointing to a basic auth protected resource, an authentication dialog appears

Screenshot_2025-10-11_at_10.33.06.png

Impact

  • IP Address Leakage: External images bypass the asset proxy security feature, allowing attackers to collect victim IP addresses directly
  • Credential Harvesting: Authentication dialogs can be triggered that appear to request GitLab credentials but actually send them to attacker-controlled domains
  • HTML Content Injection: Malicious HTML content is rendered in the deletion confirmation dialog

Original Report

Summary

Merge requests can now contain certain HTML; when rendered in most places, it's sanitized heavily and HTML payload will not render.

However, when a user tries to delete an MR that contains an HTML payload as its title, it will render through v-safe-html in the deletion dialog

Screenshot_2025-10-10_at_20.44.14.png

This can be abused by an attacker in multiple ways, even if v-safe-html is quite restricted. One way of targeting a victim is to include a payload like this

<img src="https://gittlab.com/auth/test.svg">  

Where the image is returned from my domain gittlab.com and contains a Link header that points to a basic auth protected track item, looking like this

Link: <https://gittlab.com/auth/test>; rel=preload; as=track; fetchpriority="high"  

It will render like this when a victim tries to delete it

Screenshot_2025-10-10_at_20.46.20.png

The image will render with some instructions to reauthenticate (and the linked track will trigger the auth dialog)

As can be seen, the URL in the auth dialog is my domain, but the domain in the URL is similar and is still gitlab.com, which can trick users who are not careful.

Moreover, there is also an issue that the image is bypassing asset proxy this is the information about asset proxy in the docs

A possible security concern when managing a public-facing GitLab instance is the ability to steal a user’s IP address by referencing images in issues and comments.
One way to mitigate this is by proxying any external images to a server you control.

The asset proxy is a security feature that should prevent IP leakage to attacker servers.

Steps to reproduce
  1. Log in to gitlab and go to any project you own
  2. Create a new MR
  3. Name the MR <img src="https://gittlab.com/auth/test.svg">
  4. Navigate to the MR
  5. Click Edit on the MR and then scroll to the botom to find the Delete button
  6. When trying to delete the MR you will see the auth dialog and the image from my server
Impact

Rendering external images, leaking user IP,s and triggering an authentication pop-up that can leak user credentials

Examples

Screen_Recording_2025-10-10_at_21.00.30.mov

What is the current bug behavior?

The MR title is rendered as HTML

What is the expected correct behavior?

The MR title should not render as HTML

Output of checks

This bug happens on GitLab.com

Impact

Rendering external images, leaking user IP,s and triggering an authentication pop-up that can leak user credentials

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

  • Screenshot_2025-10-10_at_20.44.14.png
  • Screenshot_2025-10-10_at_20.46.20.png
  • Screen_Recording_2025-10-10_at_21.00.30.mov

How To Reproduce

Please add reproducibility information to this section:

Assignee Loading
Time tracking Loading