Skip to content

Commit a71ca14

Browse files
authored
fix: CSP with unsafe-eval detection with Trusted Types (#27472)
1 parent f23cfbe commit a71ca14

3 files changed

Lines changed: 63 additions & 3 deletions

File tree

lib/renderer/security-warnings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const isLocalhost = function () {
7979
const isUnsafeEvalEnabled = function () {
8080
return webFrame.executeJavaScript(`(${(() => {
8181
try {
82-
new Function(''); // eslint-disable-line no-new,no-new-func
82+
eval(window.trustedTypes.emptyScript); // eslint-disable-line no-eval
8383
} catch {
8484
return false;
8585
}

spec-main/security-warnings-spec.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ describe('security warnings', () => {
2222
let server: http.Server;
2323
let w: BrowserWindow;
2424
let useCsp = true;
25+
let useTrustedTypes = false;
2526
let serverUrl: string;
2627

2728
before((done) => {
@@ -48,8 +49,11 @@ describe('security warnings', () => {
4849
return;
4950
}
5051

51-
const cspHeaders = { 'Content-Security-Policy': `script-src 'self' 'unsafe-inline'` };
52-
response.writeHead(200, useCsp ? cspHeaders : undefined);
52+
const cspHeaders = [
53+
...(useCsp ? ['script-src \'self\' \'unsafe-inline\''] : []),
54+
...(useTrustedTypes ? ['require-trusted-types-for \'script\'; trusted-types *'] : [])
55+
];
56+
response.writeHead(200, { 'Content-Security-Policy': cspHeaders });
5357
response.write(file, 'binary');
5458
response.end();
5559
});
@@ -68,6 +72,7 @@ describe('security warnings', () => {
6872

6973
afterEach(async () => {
7074
useCsp = true;
75+
useTrustedTypes = false;
7176
await closeWindow(w);
7277
w = null as unknown as any;
7378
});
@@ -129,6 +134,22 @@ describe('security warnings', () => {
129134
expect(message).to.include('Insecure Content-Security-Policy');
130135
});
131136

137+
it('should warn about insecure Content-Security-Policy (Trusted Types)', async () => {
138+
w = new BrowserWindow({
139+
show: false,
140+
webPreferences: {
141+
enableRemoteModule: false,
142+
...webPreferences
143+
}
144+
});
145+
146+
useCsp = false;
147+
useTrustedTypes = true;
148+
w.loadURL(`${serverUrl}/base-page-security.html`);
149+
const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
150+
expect(message).to.include('Insecure Content-Security-Policy');
151+
});
152+
132153
it('should warn about allowRunningInsecureContent', async () => {
133154
w = new BrowserWindow({
134155
show: false,

typings/internal-ambient.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ declare interface Window {
111111
}
112112
};
113113
ResizeObserver: ResizeObserver;
114+
trustedTypes: TrustedTypePolicyFactory;
114115
}
115116

116117
/**
@@ -162,3 +163,41 @@ interface ResizeObserverEntry {
162163
*/
163164
readonly contentRect: DOMRectReadOnly;
164165
}
166+
167+
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#trusted-types
168+
169+
type TrustedHTML = string;
170+
type TrustedScript = string;
171+
type TrustedScriptURL = string;
172+
type TrustedType = TrustedHTML | TrustedScript | TrustedScriptURL;
173+
type StringContext = 'TrustedHTML' | 'TrustedScript' | 'TrustedScriptURL';
174+
175+
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#typedef-trustedtypepolicy
176+
177+
interface TrustedTypePolicy {
178+
createHTML(input: string, ...arguments: any[]): TrustedHTML;
179+
createScript(input: string, ...arguments: any[]): TrustedScript;
180+
createScriptURL(input: string, ...arguments: any[]): TrustedScriptURL;
181+
}
182+
183+
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#typedef-trustedtypepolicyoptions
184+
185+
interface TrustedTypePolicyOptions {
186+
createHTML?: (input: string, ...arguments: any[]) => TrustedHTML;
187+
createScript?: (input: string, ...arguments: any[]) => TrustedScript;
188+
createScriptURL?: (input: string, ...arguments: any[]) => TrustedScriptURL;
189+
}
190+
191+
// https://w3c.github.io/webappsec-trusted-types/dist/spec/#typedef-trustedtypepolicyfactory
192+
193+
interface TrustedTypePolicyFactory {
194+
createPolicy(policyName: string, policyOptions: TrustedTypePolicyOptions): TrustedTypePolicy
195+
isHTML(value: any): boolean;
196+
isScript(value: any): boolean;
197+
isScriptURL(value: any): boolean;
198+
readonly emptyHTML: TrustedHTML;
199+
readonly emptyScript: TrustedScript;
200+
getAttributeType(tagName: string, attribute: string, elementNs?: string, attrNs?: string): StringContext | null;
201+
getPropertyType(tagName: string, property: string, elementNs?: string): StringContext | null;
202+
readonly defaultPolicy: TrustedTypePolicy | null;
203+
}

0 commit comments

Comments
 (0)