Markdown renderer in Gitlab Workflow VSCode extension allows arbitrary HTML attributes on whitelisted elements

**[HackerOne report #1261073](https://hackerone.com/reports/1261073)** by `arw9234` on 2021-07-14, assigned to GitLab Team:

[Report](#report) | [Attachments](#attachments) | [How To Reproduce](#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](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/src/webview_controller.ts#L104) before incorporating it into the document using the following function:

```ts  
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:  
```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](https://github.com/gjtorikian/html-pipeline/blob/v2.12.3/lib/html/pipeline/sanitization_filter.rb#L59), 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:  
```html  
<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](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/src/webview/public/index.html#L5) 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:  
1. [Install Visual Studio Code](https://code.visualstudio.com/download) and the [Gitlab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)  
2. Create a personal access token and add it to the extension to link it to your gitlab account. Instructions can be found [here](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#setup)  
3. In a new or existing project, create an issue with the following markdown in the description:  

```html  
<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>  
```

4. Assign the issue to the same user whose access token you used to set up the extension  
5. Clone the repository locally in vscode  
6. If prompted, grant trust to the repository - vscode disables all extensions if you deny trust to the repo  
7. Click the gitlab icon in the left-hand menu  
8. On the left-hand side, expand `ISSUES AND MERGE REQUESTS > Issues assigned to me`  
9. Open the newly created issue  
10. 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 open `Help > 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:  
![VSCode_Extension_Attr_Injection_1.png](https://h1.sec.gitlab.net/a/f4a66084-5a26-4967-8048-7b2043d49d7d/VSCode_Extension_Attr_Injection_1.png)

Below is a screenshot showing the CSP violations printed to the console due to the `onmouseover` handler:  
![VSCode_Extension_Attr_Injection_2.png](https://h1.sec.gitlab.net/a/efea9d95-9bee-47d6-bef5-e6552bc64a39/VSCode_Extension_Attr_Injection_2.png)

#####  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!

* [VSCode_Extension_Attr_Injection_2.png](https://h1.sec.gitlab.net/a/efea9d95-9bee-47d6-bef5-e6552bc64a39/VSCode_Extension_Attr_Injection_2.png)
* [VSCode_Extension_Attr_Injection_1.png](https://h1.sec.gitlab.net/a/f4a66084-5a26-4967-8048-7b2043d49d7d/VSCode_Extension_Attr_Injection_1.png)

## How To Reproduce

Please add [reproducibility information] to this section:

1.
1.
1.

[reproducibility information]: https://about.gitlab.com/handbook/engineering/security/#reproducibility-on-security-issues

Story points: 1.0