Hackerone: Store XSS in Gitness markdown comment editor
Name
Store XSS in Gitness markdown comment editor
Weakness
CWE-79: Cross-site Scripting (XSS) - Stored
Severity
High (7.3)
Description
An attacker can send malicous description when creating a pull request, or comment with malicious payload bellow an existing PR. Due to improper using of react-markdown-preview component, html tags is not fully sanitized, and can be rendered with xss payload.
In MarkdownViewer.tsx rehypeRewrite. The sanitizing is not sufficient, only a, input, checkbox, link
is sanitized, the rest html can be injected arbitrarily.
<MarkdownPreview
key={flag ? hash : 0}
source={markdown}
skipHtml={true}
warpperElement=data-color-mode
rehypeRewrite={(node, _index, parent) => {
if ((node as unknown as HTMLDivElement).tagName === 'a') {
if (parent && /^h(1|2|3|4|5|6)/.test((parent as unknown as HTMLDivElement).tagName)) {
parent.children = parent.children.slice(1)
}
...
}
if (
(node as unknown as HTMLDivElement).tagName === 'input' &&
(node as Unknown as Element)?.properties?.type === 'checkbox'
) {
const lineNumber = parent?.position?.start?.line ? parent?.position?.start?.line - 1 : 0
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const element = node as any
element.properties['data-line-number'] = lineNumber.toString()
element.properties.disabled = !inDescriptionBox
}
}}
rehypePlugins={[
[rehypeVideo, { test: /\/(.*)(.mp4|.mov|.webm|.mkv|.flv)$/, details: null }],
[rehypeExternalLinks, { rel: ['nofollow noreferrer noopener'], target: '_blank' }]
]}
/>
Proof of Concept
-
Create an gitness server, using following command from official tutorial:
docker run -d \ -p 3000:3000 \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /tmp/gitness:/data \ --name gitness \ --restart always \ harness/gitness
-
Create an empty repository, such as:
xss-test
-
Open
Branches
section, new branchbranch2
. After create new branch, checkout tobranch2
and create new filetest
with any content, and commit the change. -
Open
Pull Requests
section, create new pull request, set base tomain
branch and compare tobranch2
branch. InDescription
markdown editor, send payload<iframe srcdoc="<script>alert(document.cookie)</script>"></iframe>
, and press the buttoncreate pull request
. After creating the pr, an alert should pop up.
Impact
Anyone who is capable to comment on pr or create pr can post a comment on a public project pull requests and injecting the xss.
Reference
https://github.com/uiwjs/react-markdown-preview?tab=readme-ov-file#security
FIX: https://github.com/harness/gitness/commit/49f3bf151e89d59bad60b3d41b1341d7c5b66b17