mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 12:04:04 +01:00
use TrustedFunction workaround when loading extension sources inside web worker
This commit is contained in:
@@ -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() { }
|
||||
@@ -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> {
|
||||
@@ -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}`);
|
||||
|
||||
Reference in New Issue
Block a user