sanitizer.spec.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import { defaultSanitizer } from '@jupyterlab/apputils';
  4. describe('defaultSanitizer', () => {
  5. describe('#sanitize()', () => {
  6. it('should allow h1 tags', () => {
  7. const h1 = '<h1>foo</h1>';
  8. expect(defaultSanitizer.sanitize(h1)).toBe(h1);
  9. });
  10. it('should allow h2 tags', () => {
  11. const h2 = '<h2>foo</h2>';
  12. expect(defaultSanitizer.sanitize(h2)).toBe(h2);
  13. });
  14. it('should not allow svg tags', () => {
  15. const svg = '<svg>foo</svg>';
  16. expect(defaultSanitizer.sanitize(svg)).toBe('foo');
  17. });
  18. it('should allow img tags and some attributes', () => {
  19. const img =
  20. '<img src="smiley.gif" alt="Smiley face" height="42" width="42" />';
  21. expect(defaultSanitizer.sanitize(img)).toBe(img);
  22. });
  23. it('should allow span tags and class attribute', () => {
  24. const span = '<span class="foo">bar</span>';
  25. expect(defaultSanitizer.sanitize(span)).toBe(span);
  26. });
  27. it('should set the rel attribute for <a> tags to "nofollow', () => {
  28. const a = '<a rel="foo" href="bar">Baz</a>';
  29. const expected = a.replace('foo', 'nofollow');
  30. expect(defaultSanitizer.sanitize(a)).toBe(expected);
  31. });
  32. it('should allow the `data-commandlinker-command` attribute for button tags', () => {
  33. const button =
  34. '<button data-commandlinker-command="terminal:create-new" onClick={some evil code}>Create Terminal</button>';
  35. const expectedButton =
  36. '<button data-commandlinker-command="terminal:create-new">Create Terminal</button>';
  37. expect(defaultSanitizer.sanitize(button)).toBe(expectedButton);
  38. });
  39. it('should allow the class attribute for code tags', () => {
  40. const code = '<code class="foo">bar</code>';
  41. expect(defaultSanitizer.sanitize(code)).toBe(code);
  42. });
  43. it('should allow the class attribute for div tags', () => {
  44. const div = '<div class="foo">bar</div>';
  45. expect(defaultSanitizer.sanitize(div)).toBe(div);
  46. });
  47. it('should allow the class attribute for p tags', () => {
  48. const p = '<p class="foo">bar</p>';
  49. expect(defaultSanitizer.sanitize(p)).toBe(p);
  50. });
  51. it('should allow the class attribute for pre tags', () => {
  52. const pre = '<pre class="foo">bar</pre>';
  53. expect(defaultSanitizer.sanitize(pre)).toBe(pre);
  54. });
  55. it('should strip script tags', () => {
  56. const script = '<script>alert("foo")</script>';
  57. expect(defaultSanitizer.sanitize(script)).toBe('');
  58. });
  59. it('should strip iframe tags', () => {
  60. const script = '<iframe src=""></iframe>';
  61. expect(defaultSanitizer.sanitize(script)).toBe('');
  62. });
  63. it('should strip link tags', () => {
  64. const link = '<link rel="stylesheet" type="text/css" href="theme.css">';
  65. expect(defaultSanitizer.sanitize(link)).toBe('');
  66. });
  67. it('should pass through simple well-formed whitelisted markup', () => {
  68. const div = '<div><p>Hello <b>there</b></p></div>';
  69. expect(defaultSanitizer.sanitize(div)).toBe(div);
  70. });
  71. it('should allow video tags with some attributes', () => {
  72. const video =
  73. '<video src="my/video.mp4" height="42" width="42"' +
  74. ' autoplay controls loop muted></video>';
  75. expect(defaultSanitizer.sanitize(video)).toBe(video);
  76. });
  77. it('should allow audio tags with some attributes', () => {
  78. const audio =
  79. '<audio src="my/audio.ogg autoplay loop ' + 'controls muted"></audio>';
  80. expect(defaultSanitizer.sanitize(audio)).toBe(audio);
  81. });
  82. it('should allow input tags but disable them', () => {
  83. const html = defaultSanitizer.sanitize(
  84. '<input type="checkbox" checked />'
  85. );
  86. const div = document.createElement('div');
  87. let input: HTMLInputElement;
  88. div.innerHTML = html;
  89. input = div.querySelector('input')!;
  90. expect(input.disabled).toBe(true);
  91. });
  92. // Test unwanted inline CSS style stripping
  93. it('should allow harmless inline CSS', () => {
  94. const div = '<div style="color:green"></div>';
  95. expect(defaultSanitizer.sanitize(div)).toBe(div);
  96. });
  97. it("should strip 'content' properties from inline CSS", () => {
  98. const div = '<div style="color: green; content: attr(title)"></div>';
  99. expect(defaultSanitizer.sanitize(div)).toBe(
  100. '<div style="color:green"></div>'
  101. );
  102. });
  103. it("should strip 'counter-increment' properties from inline CSS", () => {
  104. const div = '<div style="counter-increment: example-counter;"></div>';
  105. expect(defaultSanitizer.sanitize(div)).toBe('<div></div>');
  106. });
  107. it("should strip 'counter-reset' properties from inline CSS", () => {
  108. const div = '<div style="counter-reset: chapter-count 0;"></div>';
  109. expect(defaultSanitizer.sanitize(div)).toBe('<div></div>');
  110. });
  111. it("should strip 'widows' properties from inline CSS", () => {
  112. const div = '<div style="widows: 2;"></div>';
  113. expect(defaultSanitizer.sanitize(div)).toBe('<div></div>');
  114. });
  115. it("should strip 'orphans' properties from inline CSS", () => {
  116. const div = '<div style="orphans: 3;"></div>';
  117. expect(defaultSanitizer.sanitize(div)).toBe('<div></div>');
  118. });
  119. });
  120. });