|
1 | 1 | from unittest import TestCase |
2 | 2 |
|
3 | | -from mistune import create_markdown |
| 3 | +from mistune import create_markdown, html |
4 | 4 |
|
5 | 5 |
|
6 | 6 | class TestSafeUrlSecurity(TestCase): |
| 7 | + def test_known_harmful_url_schemes_are_blocked(self): |
| 8 | + for url in [ |
| 9 | + "javascript:alert(1)", |
| 10 | + "vbscript:msgbox(1)", |
| 11 | + "file:///etc/passwd", |
| 12 | + "data:text/html;base64,PHNjcmlwdD4=", |
| 13 | + "feed:javascript:alert(1)", |
| 14 | + "livescript:alert(1)", |
| 15 | + "mocha:alert(1)", |
| 16 | + "view-source:javascript:alert(1)", |
| 17 | + "jar:javascript:alert(1)", |
| 18 | + "ms-its:javascript:alert(1)", |
| 19 | + "mk:@MSITStore:javascript:alert(1)", |
| 20 | + "res:javascript:", |
| 21 | + ]: |
| 22 | + rendered = html(f"[h]({url})") |
| 23 | + self.assertIn('href="#harmful-link"', rendered, url) |
| 24 | + |
| 25 | + def test_unknown_url_scheme_is_blocked(self): |
| 26 | + rendered = html("[h](x-javascript:alert(1))") |
| 27 | + |
| 28 | + self.assertIn('href="#harmful-link"', rendered) |
| 29 | + |
| 30 | + def test_reference_and_autolink_harmful_url_schemes_are_blocked(self): |
| 31 | + cases = [ |
| 32 | + "[h][r]\n\n[r]: feed:javascript:alert(1)", |
| 33 | + "<feed:javascript:alert(1)>", |
| 34 | + "[h][r]\n\n[r]: x-javascript:alert(1)", |
| 35 | + "<x-javascript:alert(1)>", |
| 36 | + ] |
| 37 | + for text in cases: |
| 38 | + rendered = create_markdown()(text) |
| 39 | + self.assertIn('href="#harmful-link"', rendered, text) |
| 40 | + |
7 | 41 | def test_percent_encoded_harmful_url_scheme_is_blocked(self): |
8 | 42 | for text in [ |
9 | 43 | "[h](javascript%3Aalert(1))", |
10 | 44 | "[h](javascript%253Aalert(1))", |
11 | 45 | "[h][r]\n\n[r]: javascript%3Aalert(1)", |
12 | 46 | "", |
13 | 47 | "[h](view-source:javascript:alert(1))", |
| 48 | + "[h](%20javascript%3Aalert(1))", |
14 | 49 | ]: |
15 | | - html = create_markdown()(text) |
16 | | - self.assertIn("#harmful-link", html, text) |
| 50 | + rendered = create_markdown()(text) |
| 51 | + self.assertIn("#harmful-link", rendered, text) |
17 | 52 |
|
18 | 53 | def test_safe_percent_encoded_data_image_is_allowed(self): |
19 | | - html = create_markdown()("") |
20 | | - self.assertIn('src="data%3Aimage/png;base64,AAAA"', html) |
| 54 | + rendered = create_markdown()("") |
| 55 | + self.assertIn('src="data%3Aimage/png;base64,AAAA"', rendered) |
| 56 | + |
| 57 | + def test_safe_url_schemes_are_allowed(self): |
| 58 | + for url in [ |
| 59 | + "http://example.com", |
| 60 | + "https://example.com", |
| 61 | + "mailto:user@example.com", |
| 62 | + "tel:+123456789", |
| 63 | + "ftp://example.com/file", |
| 64 | + "ftps://example.com/file", |
| 65 | + "irc://example.com/channel", |
| 66 | + "ircs://example.com/channel", |
| 67 | + "//example.com/path", |
| 68 | + "/path", |
| 69 | + "./path:with-colon", |
| 70 | + "../path:with-colon", |
| 71 | + "path/with:colon", |
| 72 | + "#fragment", |
| 73 | + "?query", |
| 74 | + ]: |
| 75 | + rendered = html(f"[h]({url})") |
| 76 | + self.assertIn(f'href="{url}"', rendered, url) |
0 commit comments