Skip to content

Commit

Permalink
fix: escape the language class name so it cannot be used to inject HT…
Browse files Browse the repository at this point in the history
…ML (#137)

* fix: fix: escape lang to use

* test: add unit test for XSS injection through the language name

* test: make the XSS attack test more realistic

Co-authored-by: Joshua Gleitze <dev@joshuagleitze.de>
  • Loading branch information
catnose99 and jGleitz committed Sep 29, 2020
1 parent 3ef53e5 commit c1c074b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/index.ts
Expand Up @@ -106,7 +106,7 @@ function selectLanguage(options: Options, lang: string): [string, Grammar | unde
function highlight(markdownit: MarkdownIt, options: Options, text: string, lang: string): string {
const [langToUse, prismLang] = selectLanguage(options, lang)
const code = prismLang ? Prism.highlight(text, prismLang, langToUse) : markdownit.utils.escapeHtml(text)
const classAttribute = langToUse ? ` class="${markdownit.options.langPrefix}${langToUse}"` : ''
const classAttribute = langToUse ? ` class="${markdownit.options.langPrefix}${markdownit.utils.escapeHtml(langToUse)}"` : ''
return `<pre${classAttribute}><code${classAttribute}>${code}</code></pre>`
}

Expand Down
8 changes: 7 additions & 1 deletion test/test.ts
Expand Up @@ -80,7 +80,6 @@ describe('markdown-it-prism', () => {
.use(markdownItPrism)
.render(await read('input/indented.md'))
).toEqual(await read('expected/indented.html'))

})

it('adds classes even if the language is unknown', async () => {
Expand All @@ -90,6 +89,13 @@ describe('markdown-it-prism', () => {
).toEqual(await read('expected/fenced-with-unknown-language.html'))
})

it('escapes HTML in the language name', async () => {
expect(markdownit()
.use(markdownItPrism)
.render(await read('input/fenced-with-html-in-language.md'))
).toEqual(await read('expected/fenced-with-html-in-language.html'))
})

it('falls back to defaultLanguageForUnknown if the specified language is unknown', async () => {
expect(markdownit()
.use(markdownItPrism, {
Expand Down
8 changes: 8 additions & 0 deletions testdata/expected/fenced-with-html-in-language.html
@@ -0,0 +1,8 @@
<h1>Test</h1>
<p>This is a fenced code block:</p>
<pre class="language-&quot;&gt;&lt;img/onerror=&quot;alert('hacked')&quot;src=.&gt;&lt;span\class=&quot;"><code class="language-&quot;&gt;&lt;img/onerror=&quot;alert('hacked')&quot;src=.&gt;&lt;span\class=&quot;">public class Foo() {
public Foo(bar) {
System.out.println(bar);
}
}
</code></pre>
11 changes: 11 additions & 0 deletions testdata/input/fenced-with-html-in-language.md
@@ -0,0 +1,11 @@
# Test

This is a fenced code block:

```"><img/onerror="alert('hacked')"src=.><span\class="
public class Foo() {
public Foo(bar) {
System.out.println(bar);
}
}
```

0 comments on commit c1c074b

Please sign in to comment.