Skip to content

Commit 27834d9

Browse files
committed
test(web): Markdown sanitization & extensibility
fix(web): replaces dompurify with isomorphic-dompurify to enable server-side usage with same syntax
1 parent f9c2d35 commit 27834d9

File tree

6 files changed

+430
-13
lines changed

6 files changed

+430
-13
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`sanitization > strips javascript 1`] = `
4+
"<p><img src="x"></p>
5+
"
6+
`;
7+
8+
exports[`sanitization > strips javascript 2`] = `
9+
"<p><img src="x"></p>
10+
"
11+
`;

web/helpers/markdown.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { baseUrl } from 'marked-base-url';
2+
import { describe, expect, test } from 'vitest';
3+
import { Markdown } from './markdown';
4+
5+
// add a random extension to the instance
6+
const instance = Markdown.create(baseUrl('https://unraid.net'));
7+
const parse = async (content: string) => ({
8+
fromDefault: await Markdown.parse(content),
9+
fromInstance: await instance.parse(content),
10+
});
11+
12+
describe('sanitization', () => {
13+
test('strips javascript', async () => {
14+
const parsed = await parse(`<img src=x onerror=alert(1)//><script>console.log('hello')</script>`);
15+
expect(parsed.fromDefault).toMatchSnapshot();
16+
expect(parsed.fromInstance).toMatchSnapshot();
17+
});
18+
19+
test('strips various XSS vectors', async () => {
20+
const vectors = [
21+
'<a href="javascript:alert(1)">click me</a>',
22+
"<IMG SRC=JaVaScRiPt:alert('XSS')>",
23+
'"><script>alert(document.cookie)</script>',
24+
'<style>@import \'javascript:alert("XSS")\';</style>',
25+
];
26+
27+
for (const vector of vectors) {
28+
const parsed = await parse(vector);
29+
expect(parsed.fromDefault).not.toContain('javascript:');
30+
expect(parsed.fromInstance).not.toContain('javascript:');
31+
}
32+
});
33+
});
34+
35+
describe('extensibility', () => {
36+
test('works with other extensions', async () => {
37+
const parsed = await parse(`[Contact](/contact)`);
38+
expect(parsed.fromDefault).toMatchInlineSnapshot(`
39+
"<p><a href="/contact">Contact</a></p>
40+
"
41+
`);
42+
expect(parsed.fromInstance).toMatchInlineSnapshot(`
43+
"<p><a href="https://unraid.net/contact">Contact</a></p>
44+
"
45+
`);
46+
});
47+
});

web/helpers/markdown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import DOMPurify from 'dompurify';
1+
import DOMPurify from 'isomorphic-dompurify';
22
import { Marked, type MarkedExtension } from 'marked';
33

44
const defaultMarkedExtension: MarkedExtension = {

0 commit comments

Comments
 (0)