fix: CSP with unsafe-eval detection with Trusted Types (#27446)

This commit is contained in:
Milan Burda 2021-01-25 02:31:25 +01:00 committed by GitHub
parent 4a5c5843c4
commit 64b7be751a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 3 deletions

View file

@ -81,7 +81,7 @@ const isUnsafeEvalEnabled: () => Promise<boolean> = function () {
// Call _executeJavaScript to bypass the world-safe deprecation warning // Call _executeJavaScript to bypass the world-safe deprecation warning
return (webFrame as any)._executeJavaScript(`(${(() => { return (webFrame as any)._executeJavaScript(`(${(() => {
try { try {
new Function(''); // eslint-disable-line no-new,no-new-func eval(window.trustedTypes.emptyScript); // eslint-disable-line no-eval
} catch { } catch {
return false; return false;
} }

View file

@ -22,6 +22,7 @@ describe('security warnings', () => {
let server: http.Server; let server: http.Server;
let w: BrowserWindow; let w: BrowserWindow;
let useCsp = true; let useCsp = true;
let useTrustedTypes = false;
let serverUrl: string; let serverUrl: string;
before((done) => { before((done) => {
@ -48,8 +49,11 @@ describe('security warnings', () => {
return; return;
} }
const cspHeaders = { 'Content-Security-Policy': 'script-src \'self\' \'unsafe-inline\'' }; const cspHeaders = [
response.writeHead(200, useCsp ? cspHeaders : undefined); ...(useCsp ? ['script-src \'self\' \'unsafe-inline\''] : []),
...(useTrustedTypes ? ['require-trusted-types-for \'script\'; trusted-types *'] : [])
];
response.writeHead(200, { 'Content-Security-Policy': cspHeaders });
response.write(file, 'binary'); response.write(file, 'binary');
response.end(); response.end();
}); });
@ -68,6 +72,7 @@ describe('security warnings', () => {
afterEach(async () => { afterEach(async () => {
useCsp = true; useCsp = true;
useTrustedTypes = false;
await closeWindow(w); await closeWindow(w);
w = null as unknown as any; w = null as unknown as any;
}); });
@ -129,6 +134,22 @@ describe('security warnings', () => {
expect(message).to.include('Insecure Content-Security-Policy'); expect(message).to.include('Insecure Content-Security-Policy');
}); });
it('should warn about insecure Content-Security-Policy (Trusted Types)', async () => {
w = new BrowserWindow({
show: false,
webPreferences: {
enableRemoteModule: false,
...webPreferences
}
});
useCsp = false;
useTrustedTypes = true;
w.loadURL(`${serverUrl}/base-page-security.html`);
const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
expect(message).to.include('Insecure Content-Security-Policy');
});
it('should warn about allowRunningInsecureContent', async () => { it('should warn about allowRunningInsecureContent', async () => {
w = new BrowserWindow({ w = new BrowserWindow({
show: false, show: false,

View file

@ -272,6 +272,7 @@ declare interface Window {
} }
}; };
ResizeObserver: ResizeObserver; ResizeObserver: ResizeObserver;
trustedTypes: TrustedTypePolicyFactory;
} }
/** /**
@ -323,3 +324,41 @@ interface ResizeObserverEntry {
*/ */
readonly contentRect: DOMRectReadOnly; readonly contentRect: DOMRectReadOnly;
} }
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types
type TrustedHTML = string;
type TrustedScript = string;
type TrustedScriptURL = string;
type TrustedType = TrustedHTML | TrustedScript | TrustedScriptURL;
type StringContext = 'TrustedHTML' | 'TrustedScript' | 'TrustedScriptURL';
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#typedef-trustedtypepolicy
interface TrustedTypePolicy {
createHTML(input: string, ...arguments: any[]): TrustedHTML;
createScript(input: string, ...arguments: any[]): TrustedScript;
createScriptURL(input: string, ...arguments: any[]): TrustedScriptURL;
}
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#typedef-trustedtypepolicyoptions
interface TrustedTypePolicyOptions {
createHTML?: (input: string, ...arguments: any[]) => TrustedHTML;
createScript?: (input: string, ...arguments: any[]) => TrustedScript;
createScriptURL?: (input: string, ...arguments: any[]) => TrustedScriptURL;
}
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#typedef-trustedtypepolicyfactory
interface TrustedTypePolicyFactory {
createPolicy(policyName: string, policyOptions: TrustedTypePolicyOptions): TrustedTypePolicy
isHTML(value: any): boolean;
isScript(value: any): boolean;
isScriptURL(value: any): boolean;
readonly emptyHTML: TrustedHTML;
readonly emptyScript: TrustedScript;
getAttributeType(tagName: string, attribute: string, elementNs?: string, attrNs?: string): StringContext | null;
getPropertyType(tagName: string, property: string, elementNs?: string): StringContext | null;
readonly defaultPolicy: TrustedTypePolicy | null;
}