diff options
author | David Cho-Lerat <david.cho-lerat@sonarsource.com> | 2024-10-03 10:09:00 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-10-08 20:02:47 +0000 |
commit | c9ecf7fa2f9af18f474a2aea2c7c3cefd3a6e80f (patch) | |
tree | 40b9f0694c1bd3baaee84ade9fa4059b851c7ae2 /server/sonar-web/src/main/js/helpers | |
parent | 12664adb48e6b95e521b0e05d81f916af2a88bc4 (diff) | |
download | sonarqube-c9ecf7fa2f9af18f474a2aea2c7c3cefd3a6e80f.tar.gz sonarqube-c9ecf7fa2f9af18f474a2aea2c7c3cefd3a6e80f.zip |
SONAR-23249 Fix SSF-656 & SSF-657
Diffstat (limited to 'server/sonar-web/src/main/js/helpers')
4 files changed, 7 insertions, 226 deletions
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/code-difference-test.tsx b/server/sonar-web/src/main/js/helpers/__tests__/code-difference-test.tsx index fe90bf7bfa6..f65317b396d 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/code-difference-test.tsx +++ b/server/sonar-web/src/main/js/helpers/__tests__/code-difference-test.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { render } from '@testing-library/react'; +import { SafeHTMLInjection } from 'design-system/lib'; import React from 'react'; import applyCodeDifferences from '../code-difference'; @@ -146,12 +147,8 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t function renderDom(codeSnippet: string) { return render( - <div - className="markdown" - // eslint-disable-next-line react/no-danger - dangerouslySetInnerHTML={{ - __html: codeSnippet, - }} - />, + <SafeHTMLInjection htmlAsString={codeSnippet}> + <div className="markdown" /> + </SafeHTMLInjection>, ); } diff --git a/server/sonar-web/src/main/js/helpers/__tests__/sanitize-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/sanitize-test.ts deleted file mode 100644 index f219b154746..00000000000 --- a/server/sonar-web/src/main/js/helpers/__tests__/sanitize-test.ts +++ /dev/null @@ -1,160 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { sanitizeString, sanitizeStringRestricted } from '../sanitize'; - -describe('sanitizeStringRestricted', () => { - it('should preserve only specific formatting tags', () => { - expect( - sanitizeStringRestricted(` - Hi <a href="http://example.com" target="_blank">this</a> is <i>in italics</i> and <ul> - <li> lists </li> - <li> are allowed</li> - </ul> - <p> - as well. This is <b>Amazing</b> and this <strong>bold</strong> <br> - and <code>code.is.accepted too</code> - </p> - `), - ).toBe(` - Hi <a target="_blank" href="http://example.com">this</a> is <i>in italics</i> and <ul> - <li> lists </li> - <li> are allowed</li> - </ul> - <p> - as well. This is <b>Amazing</b> and this <strong>bold</strong> <br> - and <code>code.is.accepted too</code> - </p> - `); - }); - - /* - * Test code borrowed from OWASP's sanitizer tests - * https://github.com/OWASP/java-html-sanitizer/blob/master/src/test/resources/org/owasp/html/htmllexerinput1.html - */ - it('should strip everything else', () => { - const clean = sanitizeStringRestricted(`<?xml version="not-even-close"?> - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> - - <!-- a test input for HtmlLexer --> - - <html> - <head> - <title>Test File For HtmlLexer & HtmlParser</title> - <link rel=stylesheet type="text/css" src=foo/bar.css /> - <body - bgcolor=white - linkcolor = "blue" - onload="document.writeln( - "<p>properly escaped code in a handler</p>");" - > - - <script type="text/javascript"><!-- - document.writeln("<p>Some initialization code in global context</p>"); - --></script> - - <script type="text/javascript"> - // hi there - document.writeln("<p>More initialization</p>"); - </script> - - <div id=clickydiv onclick="handleClicky(event)" - ondblclick=this.onclick(event);return(false)> - Clicky - </div> - - <input id=foo> - <gxp:attr name="onchange">alert("<b>hi</b>");</gxp:attr> - </input> - - <pre><div id=notarealtag onclick=notcode()></pre> - - <!-- some tokenization corner cases --> - - < notatag <atag/> - - </ notatag> </redundantlyclosed/> - - <messyattributes a=b=c d="e"f=g h =i j= k l = m checked n="o"/> - - < < < all in one text block > > > - - <xmp>Make sure that <!-- comments don't obscure the xmp close</xmp> - <% # some php code here - write("<pre>$horriblySyntacticConstruct1</pre>\n\n"); - %> - <script type="text/javascript"><!-- - alert("hello world"); - // --></script> - - <script>/* </script> */alert('hi');</script> - <script><!--/* </script> */alert('hi');--></script> - - <xmp style=color:blue><!--/* </xmp> */alert('hi');--></xmp> - - <style><!-- p { contentf: '</style>' } --></style> - <style>Foo<!-- > </style> --></style> - <textarea><!-- Zoicks </textarea>--></textarea> - <!-- An escaping text span start may share its U+002D HYPHEN-MINUS characters - - with its corresponding escaping text span end. --> - <script><!--></script> - <script><!---></script> - <script><!----></script> - </body> - </html> - <![CDATA[ No such thing as a CDATA> section in HTML ]]> - <script>a<b</script> - <img src=foo.gif /><a href=><a href=/> - <span title=malformed attribs' do=don't id=foo checked onclick="a<b">Bar</span>`); - - expect(clean.replace(/\s+/g, '')).toBe( - `Clickyalert("<b>hi</b>");<divid=notarealtagonclick=notcode()><notatag<<<allinonetextblock>>><%#somephpcodeherewrite("$horriblySyntacticConstruct1");%>*/alert('hi');*/alert('hi');-->*/alert('hi');-->'}-->--><!--Zoicks-->sectioninHTML]]><ahref=""></a><ahref="/">Bar</a>`, - ); - }); -}); - -describe('sanitizeString', () => { - it('should not allow MathML and SVG', () => { - const tainted = ` - Hi <a href="javascript:alert('hello')" target="_blank">this</a> is <i>in italics</i> and <ul> - <li> lists </li> - <li> are allowed</li> - </ul> - <p class="some-class"> - as well. This is <b>Amazing</b> and this <strong>bold</strong> <br> - and <code>code.is.accepted too</code> - </p> - <svg><text>SVG isn't allowed</text></svg> - <math xmlns="http://www.w3.org/1998/Math/MathML"> - <infinity /> - </math>`; - const clean = ` - Hi <a>this</a> is <i>in italics</i> and <ul> - <li> lists </li> - <li> are allowed</li> - </ul> - <p class="some-class"> - as well. This is <b>Amazing</b> and this <strong>bold</strong> <br> - and <code>code.is.accepted too</code> - </p>`; - - expect(sanitizeString(tainted).trimRight()).toBe(clean); - }); -}); diff --git a/server/sonar-web/src/main/js/helpers/code-difference.ts b/server/sonar-web/src/main/js/helpers/code-difference.ts index ff7653546b2..2caaae10460 100644 --- a/server/sonar-web/src/main/js/helpers/code-difference.ts +++ b/server/sonar-web/src/main/js/helpers/code-difference.ts @@ -17,9 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +import { sanitizeHTMLNoSVGNoMathML } from 'design-system'; import { diffLines } from 'diff'; import { groupBy, keyBy } from 'lodash'; -import { sanitizeString } from './sanitize'; const NUMBER_OF_EXAMPLES = 2; @@ -85,7 +86,7 @@ function differentiateCode(compliant: string, nonCompliant: string) { nonCompliantCode += `<div class='code-removed'>${value}</div>`; } }); - return [sanitizeString(nonCompliantCode), sanitizeString(compliantCode)]; + return [sanitizeHTMLNoSVGNoMathML(nonCompliantCode), sanitizeHTMLNoSVGNoMathML(compliantCode)]; } function replaceInDom(current: Element, code: string) { diff --git a/server/sonar-web/src/main/js/helpers/sanitize.ts b/server/sonar-web/src/main/js/helpers/sanitize.ts deleted file mode 100644 index acdae5799ca..00000000000 --- a/server/sonar-web/src/main/js/helpers/sanitize.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { sanitize } from 'dompurify'; - -export function sanitizeStringRestricted(html: string) { - return sanitize(html, { - ALLOWED_TAGS: ['b', 'br', 'code', 'i', 'li', 'p', 'strong', 'ul', 'a'], - ALLOWED_ATTR: ['target', 'href'], - }); -} - -export function sanitizeString(html: string) { - return sanitize(html, { USE_PROFILES: { html: true } }); -} - -export function sanitizeUserInput(html: string) { - return sanitize(html, { - ALLOWED_TAGS: [ - 'b', - 'br', - 'code', - 'i', - 'li', - 'p', - 'strong', - 'ul', - 'ol', - 'a', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'blockquote', - 'pre', - ], - ALLOWED_ATTR: ['target', 'href', 'rel'], - }); -} |