diff --git a/katas/content/linear_algebra/index.md b/katas/content/linear_algebra/index.md index db4cf78e9dd..61c5991dee9 100644 --- a/katas/content/linear_algebra/index.md +++ b/katas/content/linear_algebra/index.md @@ -219,7 +219,7 @@ A square matrix has a property called the **determinant**, with the determinant For a $2 \times 2$ matrix $A$, the determinant is defined as $|A| = A_{0,0} \cdot A_{1,1} - A_{0,1} \cdot A_{1,0}$. -For larger matrices, the determinant is defined through determinants of sub-matrices. You can learn more about the determinant of matrices from [Wikipedia](https://en.wikipedia.org/wiki/Determinant) or from [Wolfram MathWorld](http://mathworld.wolfram.com/Determinant.html). +For larger matrices, the determinant is defined through determinants of sub-matrices. You can learn more about the determinant of matrices from [Wikipedia](https://en.wikipedia.org/wiki/Determinant) or from [Wolfram MathWorld](https://mathworld.wolfram.com/Determinant.html). @[exercise]({ "id": "linear_algebra__inverse_matrix_ex", diff --git a/source/playground/src/main.tsx b/source/playground/src/main.tsx index 1c712cff924..b40fcc5c66f 100644 --- a/source/playground/src/main.tsx +++ b/source/playground/src/main.tsx @@ -58,12 +58,18 @@ import { decodeGatesUrl, } from "qsharp-lang/ux"; +import DOMPurify from "dompurify"; const md = markdownIt("commonmark"); md.use((mk as any).default, { enableMathBlockInHtml: true, enableMathInlineInHtml: true, }); // Not sure why it's not using the default export automatically :-/ -setRenderer((input: string) => md.render(input)); +// Allow only the protocols used in doc/kata/estimator content +// Borrowed from DOMPurify and filtered to our protocols +const ALLOWED_URI = /^(?:(?:https|xref):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i; +setRenderer((input: string) => + DOMPurify.sanitize(md.render(input), { ALLOWED_URI_REGEXP: ALLOWED_URI }), +); export type ActiveTab = | "results-tab" diff --git a/source/vscode/src/webview/help.tsx b/source/vscode/src/webview/help.tsx index 24718a3d54e..66ab365234c 100644 --- a/source/vscode/src/webview/help.tsx +++ b/source/vscode/src/webview/help.tsx @@ -3,8 +3,6 @@ import { useEffect, useRef } from "preact/hooks"; -declare const resourcesUri: string; // Set by the HTML in the window - let svgPromise: Promise; export function HelpPage() { @@ -14,6 +12,7 @@ export function HelpPage() { // Ensure that the fetch is kicked off once for the module if (!svgPromise) { + const resourcesUri = document.body.dataset.resourcesUri ?? ""; svgPromise = fetch(`${resourcesUri}/DebugDropDown.svg`); } diff --git a/source/vscode/src/webview/webview.tsx b/source/vscode/src/webview/webview.tsx index 23b8ed3ced4..5ec3b5bc3b9 100644 --- a/source/vscode/src/webview/webview.tsx +++ b/source/vscode/src/webview/webview.tsx @@ -20,16 +20,22 @@ import { HelpPage } from "./help"; import { DocumentationView, IDocFile } from "./docview"; import "./webview.css"; +import DOMPurify from "dompurify"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - there are no types for this import mk from "@vscode/markdown-it-katex"; import markdownIt from "markdown-it"; -const md = markdownIt("commonmark"); +const md = markdownIt("commonmark", { html: false }); md.use(mk, { enableMathBlockInHtml: true, enableMathInlineInHtml: true, }); -setRenderer((input: string) => md.render(input)); +// Allow only the protocols used in doc/kata/estimator content +// Borrowed from DOMPurify and filtered to our protocols +const ALLOWED_URI = /^(?:(?:https|xref):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i; +setRenderer((input: string) => + DOMPurify.sanitize(md.render(input), { ALLOWED_URI_REGEXP: ALLOWED_URI }), +); window.addEventListener("message", onMessage); window.addEventListener("load", main); diff --git a/source/vscode/src/webviewPanel.ts b/source/vscode/src/webviewPanel.ts index e7f4c199378..3186aefe244 100644 --- a/source/vscode/src/webviewPanel.ts +++ b/source/vscode/src/webviewPanel.ts @@ -336,23 +336,24 @@ export class QSharpWebViewPanel { const webviewCss = getUri(["out", "webview", "webview.css"]); const webviewJs = getUri(["out", "webview", "webview.js"]); const resourcesUri = getUri(["resources"]); + const cspSource = webview.cspSource; return /*html*/ ` + Q# - - + + `;