Repository navigation
fix(code-editor): sanitize raw HTML rendered by Markdown - #1775
Priyank-gouda678 wants to merge 1 commit into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request introduces HTML sanitization to the Markdown component by adding the rehype-sanitize plugin and includes a test to verify that unsafe tags like iframe, script, and form are stripped. The review feedback recommends expanding this test to also verify that unsafe protocols, such as javascript: on anchor tags, are successfully sanitized.
| test('it strips unsafe raw html', () => { | ||
| const markdown = `Text <iframe src="javascript:alert(1)"></iframe> | ||
| <iframe srcdoc="<script>alert(1)</script>"></iframe> | ||
| <script>alert(1)</script> | ||
| <form action="javascript:alert(1)"><button>go</button></form>`; | ||
| const { container } = renderWithTheme(<Markdown source={markdown} />); | ||
| // eslint-disable-next-line testing-library/no-container | ||
| expect(container.querySelector('iframe, script, form')).toBeNull(); | ||
| expect(screen.getByText(/Text/)).toBeInTheDocument(); | ||
| }); |
There was a problem hiding this comment.
While the test successfully verifies that unsafe tags like iframe, script, and form are stripped, it does not verify that unsafe protocols (such as javascript:) on allowed tags like <a> are also sanitized. Since javascript: links are a very common XSS vector in Markdown, it is highly recommended to expand the test coverage to assert that these attributes are stripped.
test('it strips unsafe raw html and protocols', () => {
const markdown = `Text <iframe src="javascript:alert(1)"></iframe>
<iframe srcdoc="<script>alert(1)</script>"></iframe>
<script>alert(1)</script>
<form action="javascript:alert(1)"><button>go</button></form>
[dangerous link](javascript:alert(1))
<a href="javascript:alert(1)">dangerous raw link</a>`;
const { container } = renderWithTheme(<Markdown source={markdown} />);
// eslint-disable-next-line testing-library/no-container
expect(container.querySelector('iframe, script, form')).toBeNull();
expect(screen.getByText(/Text/)).toBeInTheDocument();
// eslint-disable-next-line testing-library/no-container
const links = container.querySelectorAll('a');
links.forEach(link => {
expect(link.getAttribute('href')).toBeNull();
});
});
Markdownin@looker/code-editorrunsrehype-rawwith no sanitizer, so raw HTML in the markdown source becomes live DOM.<iframe src="javascript:...">,<iframe srcdoc="<script>...">,<form action="javascript:...">and<script>all render unchanged (React only drops stringon*handlers), and jsdom executes thejavascript:iframe during the test run. The hackathon extension feeds participant-written project descriptions and judge notes into this component throughExtMarkdown(ProjectView,JudgingView), so one hacker can run script as any other hacker or judge who opens the project, inside the Looker extension with that user's API access. run-it also renderstext/markdownAPI responses through it.The fix adds
rehype-sanitize(v4, the release that matches react-markdown 6 / unified 9) afterrehype-raw, so the GitHub allowlist schema decides which elements, attributes and URL protocols survive.<mark>search highlighting, tables, code blocks and relative/https links keep working, and the existing code-editor, api-explorer, run-it, extension-utils and hackathon scene tests pass. A regression test inMarkdown.spec.tsxfails before the change and passes after.Developer Checklist ℹ️