Skip to content

Commit

Permalink
use TrustedFunction workaround when loading extension sources inside …
Browse files Browse the repository at this point in the history
…web worker
  • Loading branch information
jrieken committed Jan 8, 2021
1 parent eb940d4 commit 44c9b4b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/vs/code/electron-browser/workbench/workbench.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'none'; frame-src 'self' vscode-webview: https://*.vscode-webview-test.com; object-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types default amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget domLineBreaksComputer editorViewLayer extensionHostWorker insane notebookOutputRenderer safeInnerHtml standaloneColorizer tokenizeToString webNestedWorkerExtensionHost webWorkerExtensionHost;">
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types default TrustedFunctionWorkaround ExtensionScripts amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget domLineBreaksComputer editorViewLayer extensionHostWorker insane notebookOutputRenderer safeInnerHtml standaloneColorizer tokenizeToString webNestedWorkerExtensionHost webWorkerExtensionHost;">
</head>
<body aria-label="">
</body>
Expand Down
35 changes: 34 additions & 1 deletion src/vs/workbench/api/worker/extHostExtensionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes';
import { timeout } from 'vs/base/common/async';

namespace TrustedFunction {

// workaround a chrome issue not allowing to create new functions
// see https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
const ttpTrustedFunction = self.trustedTypes?.createPolicy('TrustedFunctionWorkaround', {
createScript: (_, ...args: string[]) => {
args.forEach((arg) => {
if (!self.trustedTypes?.isScript(arg)) {
throw new Error('TrustedScripts only, please');
}
});
// NOTE: This is insecure without parsing the arguments and body,
// Malicious inputs can escape the function body and execute immediately!
const fnArgs = args.slice(0, -1).join(',');
const fnBody = args.pop()!.toString();
const body = `(function anonymous(${fnArgs}) {\n${fnBody}\n})`;
return body;
}
});

export function create(...args: string[]): Function {
return self.eval(ttpTrustedFunction?.createScript('', ...args) as unknown as string);
}
}

class WorkerRequireInterceptor extends RequireInterceptor {

_installInterceptor() { }
Expand All @@ -35,6 +60,8 @@ class WorkerRequireInterceptor extends RequireInterceptor {
export class ExtHostExtensionService extends AbstractExtHostExtensionService {
readonly extensionRuntime = ExtensionRuntime.Webworker;

private static _ttpExtensionScripts = self.trustedTypes?.createPolicy('ExtensionScripts', { createScript: source => source });

private _fakeModules?: WorkerRequireInterceptor;

protected async _beforeAlmostReadyToRunExtensions(): Promise<void> {
Expand Down Expand Up @@ -71,9 +98,15 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
// Here we append #vscode-extension to serve as a marker, such that source maps
// can be adjusted for the extra wrapping function.
const sourceURL = `${module.toString(true)}#vscode-extension`;
const fullSource = `${source}\n//# sourceURL=${sourceURL}`;
let initFn: Function;
try {
initFn = new Function('module', 'exports', 'require', `${source}\n//# sourceURL=${sourceURL}`);
initFn = TrustedFunction.create(
ExtHostExtensionService._ttpExtensionScripts?.createScript('module') as unknown as string ?? 'module',
ExtHostExtensionService._ttpExtensionScripts?.createScript('exports') as unknown as string ?? 'exports',
ExtHostExtensionService._ttpExtensionScripts?.createScript('require') as unknown as string ?? 'require',
ExtHostExtensionService._ttpExtensionScripts?.createScript(fullSource) as unknown as string ?? fullSource
);
} catch (err) {
if (extensionId) {
console.error(`Loading code for extension ${extensionId.value} failed: ${err.message}`);
Expand Down

0 comments on commit 44c9b4b

Please sign in to comment.