Skip to content

Commit 97dec17

Browse files
authored
Merge pull request #569 from microsoft/dev/mjbvz/notebook-html-174-fix
Safer construction of notebook html (MSRC fix)
2 parents 30cda85 + 9a7d3f9 commit 97dec17

File tree

3 files changed

+14
-31
lines changed

3 files changed

+14
-31
lines changed

src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,20 @@ export class OutputElement extends Disposable {
128128

129129
private _renderSearchForMimetype(viewModel: ICellOutputViewModel, mimeType: string): IInsetRenderOutput {
130130
const query = `@tag:notebookRenderer ${mimeType}`;
131+
132+
const p = DOM.$('p', undefined, `No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.`);
133+
const a = DOM.$('a', { href: `command:workbench.extensions.search?%22${query}%22`, class: 'monaco-button monaco-text-button', tabindex: 0, role: 'button', style: 'padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;' }, `Search Marketplace`);
134+
131135
return {
132136
type: RenderOutputType.Html,
133137
source: viewModel,
134-
htmlContent: `<p>No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.</p>
135-
<a href="command:workbench.extensions.search?%22${query}%22" class="monaco-button monaco-text-button" tabindex="0" role="button" style="padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;">Search Marketplace</a>`
138+
htmlContent: p.outerHTML + a.outerHTML,
136139
};
137140
}
138141

139142
private _renderMessage(viewModel: ICellOutputViewModel, message: string): IInsetRenderOutput {
140-
return { type: RenderOutputType.Html, source: viewModel, htmlContent: `<p>${message}</p>` };
143+
const el = DOM.$('p', undefined, message);
144+
return { type: RenderOutputType.Html, source: viewModel, htmlContent: el.outerHTML };
141145
}
142146

143147
private async pickActiveMimeTypeRenderer(notebookTextModel: NotebookTextModel, viewModel: ICellOutputViewModel) {

src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,20 @@ class CellOutputElement extends Disposable {
236236

237237
private _renderSearchForMimetype(viewModel: ICellOutputViewModel, mimeType: string): IInsetRenderOutput {
238238
const query = `@tag:notebookRenderer ${mimeType}`;
239+
240+
const p = DOM.$('p', undefined, `No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.`);
241+
const a = DOM.$('a', { href: `command:workbench.extensions.search?%22${query}%22`, class: 'monaco-button monaco-text-button', tabindex: 0, role: 'button', style: 'padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;' }, `Search Marketplace`);
242+
239243
return {
240244
type: RenderOutputType.Html,
241245
source: viewModel,
242-
htmlContent: `<p>No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.</p>
243-
<a href="command:workbench.extensions.search?%22${query}%22" class="monaco-button monaco-text-button" tabindex="0" role="button" style="padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;">Search Marketplace</a>`
246+
htmlContent: p.outerHTML + a.outerHTML
244247
};
245248
}
246249

247250
private _renderMessage(viewModel: ICellOutputViewModel, message: string): IInsetRenderOutput {
248-
return { type: RenderOutputType.Html, source: viewModel, htmlContent: `<p>${message}</p>` };
251+
const el = DOM.$('p', undefined, message);
252+
return { type: RenderOutputType.Html, source: viewModel, htmlContent: el.outerHTML };
249253
}
250254

251255
private async _attachToolbar(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, index: number, mimeTypes: readonly IOrderedMimeType[]) {

src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -182,30 +182,6 @@ async function webviewPreloads(ctx: PreloadContext) {
182182

183183
document.body.addEventListener('click', handleInnerClick);
184184

185-
const preservedScriptAttributes: (keyof HTMLScriptElement)[] = [
186-
'type', 'src', 'nonce', 'noModule', 'async',
187-
];
188-
189-
// derived from https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/core/DOMEval.js
190-
const domEval = (container: Element) => {
191-
const arr = Array.from(container.getElementsByTagName('script'));
192-
for (let n = 0; n < arr.length; n++) {
193-
const node = arr[n];
194-
const scriptTag = document.createElement('script');
195-
const trustedScript = ttPolicy?.createScript(node.innerText) ?? node.innerText;
196-
scriptTag.text = trustedScript as string;
197-
for (const key of preservedScriptAttributes) {
198-
const val = node[key] || node.getAttribute && node.getAttribute(key);
199-
if (val) {
200-
scriptTag.setAttribute(key, val as any);
201-
}
202-
}
203-
204-
// TODO@connor4312: should script with src not be removed?
205-
container.appendChild(scriptTag).parentNode!.removeChild(scriptTag);
206-
}
207-
};
208-
209185
async function loadScriptSource(url: string, originalUri: string): Promise<string> {
210186
const res = await fetch(url);
211187
const text = await res.text();
@@ -2312,7 +2288,6 @@ async function webviewPreloads(ctx: PreloadContext) {
23122288
if (content.type === 0 /* RenderOutputType.Html */) {
23132289
const trustedHtml = ttPolicy?.createHTML(content.htmlContent) ?? content.htmlContent;
23142290
this.element.innerHTML = trustedHtml as string;
2315-
domEval(this.element);
23162291
} else if (preloadErrors.some(e => e instanceof Error)) {
23172292
const errors = preloadErrors.filter((e): e is Error => e instanceof Error);
23182293
showRenderError(`Error loading preloads`, this.element, errors);

0 commit comments

Comments
 (0)