Markdown renderer in Gitlab Workflow VSCode extension allows arbitrary HTML attributes on whitelisted elements
HackerOne report #1261073 by arw9234
on 2021-07-14, assigned to GitLab Team:
Report | Attachments | How To Reproduce
Report
Summary
I'm not sure whether something like this would be accepted without a larger impact, but I figured I should report it nonetheless.
The Gitlab VSCode extension renders gitlab flavored markdown in a few places, mostly just in issues and merge requests. When doing so, it sends the markdown to be rendered to the connected Gitlab instance where it is processed server-side. However, the extension then mutates the resulting HTML with regexes before incorporating it into the document using the following function:
private createMessageHandler = (
panel: vscode.WebviewPanel,
issuable: RestIssuable,
repositoryRoot: string,
) => async (message: any) => {
const instanceUrl = await getInstanceUrl(repositoryRoot);
if (message.command === 'renderMarkdown') {
let rendered = await gitLabService.renderMarkdown(message.markdown, repositoryRoot); // <--- clean HTML from server
rendered = (rendered || '')
.replace(/ src=".*" alt/gim, ' alt') // <--- dangerous alteration of HTML with regexes
.replace(/" data-src/gim, '" src')
.replace(/ href="\//gim, ` href="${instanceUrl}/`);
// ...
}
The above code attempts to remove/alter specific attributes within the resulting HTML. In particular, the / src=".*" alt/gim
regex tries to remove src
attributes followed by an alt
attribute, but could be made to break out of quoted attributes or change the nesting order of elements. For example, the following HTML:
<div color=" src=" title="" alt=" someattr='somevalue'"></div>
Will pass through Gitlab's markdown renderer relatively unchanged (color
, title
, and alt
are whitelisted on all elements, and <div>
is a whitelisted element), but the src=" title="" alt
sequence would then be matched and replaced by alt
with the above regex, resulting in:
<div color=" alt=" someattr="somevalue" "=""></div>
Where the someattr
attribute has broken out of the alt
attribute and became part of the DOM. This allows for arbitrary HTML attributes to be added to any element whitelisted by the sanitization filter.
This is limited, however, in that the affected frame is using a nonce-based CSP that restricts inline event handlers and javascript:
URIs. If it were possible to inject arbitrary HTML elements as well, it could be possible to inject <iframe>
/,<object>
tags since the object-src
directive is missing from the CSP. This would most likely require gitlab's GFM renderer to emit unescaped angle bracket characters in a quoted attribute, which it does not seem very keen on doing, but I will keep looking into it.
Steps to reproduce
You can reproduce this yourself as follows:
- Install Visual Studio Code and the Gitlab Workflow extension
- Create a personal access token and add it to the extension to link it to your gitlab account. Instructions can be found here
- In a new or existing project, create an issue with the following markdown in the description:
<div color=" src=" title="" alt=" style='display: block; position: absolute; width: 100vw; height: 100vh; left: 0; top: 0; z-index: 999999; background-color: black;' onmouseover='throw /this will raise a CSP violation/'">
<h1>arbitrary style attr injected</h1>
</div>
- Assign the issue to the same user whose access token you used to set up the extension
- Clone the repository locally in vscode
- If prompted, grant trust to the repository - vscode disables all extensions if you deny trust to the repo
- Click the gitlab icon in the left-hand menu
- On the left-hand side, expand
ISSUES AND MERGE REQUESTS > Issues assigned to me
- Open the newly created issue
- The editor window will be filled with a black menu with the text 'arbitrary style attr injected', indicating the
style
attribute was injected into the DOM. You can also openHelp > Toggle Developer Tools
to see the source code for the page and to see CSP violations printed to the console
Impact
An attacker can submit a malicious issue/merge request to a project that could contain arbitrary HTML attributes on whitelisted elements when opened in vscode. The impact of this is limited with inline event handlers blocked by the CSP, but this could still allow restyling of the page, injecting hrefs with arbitrary protocols on anchor elements (javascript:
uris obviously won't be executed, but other protocols could be used, such as custom protocols registered by other applications), and injecting other potentially dangerous attributes.
Examples
See the attached OVA.
What is the current bug behavior?
The markdown renderer in the GitLab Workflow VSCode extension uses a poorly designed regex to alter attributes on HTML elements which can be induced to change the structure of the HTML returned from the server.
What is the expected correct behavior?
The markdown renderer should either:
- not change the HTML returned from the server, or
- parse the HTML and update the relevant attributes using setAttribute(...)
/removeAttribute(...)
/similar before inserting it into the DOM
so that the structure of the document is not changed
Relevant logs and/or screenshots
Below is a screenshot of what the window should look like after opening the issue:
Below is a screenshot showing the CSP violations printed to the console due to the onmouseover
handler:
Output of checks
Not applicable to GitLab.com
Results of GitLab environment info
N/A
Best regards,
[@]arw9234
Impact
An attacker can submit a malicious issue/merge request to a project that could contain arbitrary HTML attributes on whitelisted elements when opened in vscode, allowing for restyling of the page, injecting hrefs with arbitrary protocols on anchor elements, and injecting other potentially dangerous attributes. A CSP bypass or ability to inject <object>
tags could potentially increase impact.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section: