123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- import { expect } from 'chai';
- import * as http from 'http';
- import * as fs from 'fs';
- import * as path from 'path';
- import * as url from 'url';
- import { BrowserWindow, WebPreferences } from 'electron/main';
- import { closeWindow } from './window-helpers';
- import { AddressInfo } from 'net';
- import { emittedUntil } from './events-helpers';
- import { ifit } from './spec-helpers';
- const features = process._linkedBinding('electron_common_features');
- const messageContainsSecurityWarning = (event: Event, level: number, message: string) => {
- return message.indexOf('Electron Security Warning') > -1;
- };
- const isLoaded = (event: Event, level: number, message: string) => {
- return (message === 'loaded');
- };
- describe('security warnings', () => {
- let server: http.Server;
- let w: BrowserWindow;
- let useCsp = true;
- let useTrustedTypes = false;
- let serverUrl: string;
- before((done) => {
- // Create HTTP Server
- server = http.createServer((request, response) => {
- const uri = url.parse(request.url!).pathname!;
- let filename = path.join(__dirname, '..', 'spec', 'fixtures', 'pages', uri);
- fs.stat(filename, (error, stats) => {
- if (error) {
- response.writeHead(404, { 'Content-Type': 'text/plain' });
- response.end();
- return;
- }
- if (stats.isDirectory()) {
- filename += '/index.html';
- }
- fs.readFile(filename, 'binary', (err, file) => {
- if (err) {
- response.writeHead(404, { 'Content-Type': 'text/plain' });
- response.end();
- return;
- }
- const cspHeaders = [
- ...(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.end();
- });
- });
- }).listen(0, '127.0.0.1', () => {
- serverUrl = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;
- done();
- });
- });
- after(() => {
- // Close server
- server.close();
- server = null as unknown as any;
- });
- afterEach(async () => {
- useCsp = true;
- useTrustedTypes = false;
- await closeWindow(w);
- w = null as unknown as any;
- });
- it('should warn about Node.js integration with remote content', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false
- }
- });
- w.loadURL(`${serverUrl}/base-page-security.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('Node.js Integration with Remote Content');
- });
- it('should not warn about Node.js integration with remote content from localhost', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
- });
- w.loadURL(`${serverUrl}/base-page-security-onload-message.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', isLoaded);
- expect(message).to.not.include('Node.js Integration with Remote Content');
- });
- const generateSpecs = (description: string, webPreferences: WebPreferences) => {
- describe(description, () => {
- it('should warn about disabled webSecurity', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- webSecurity: false,
- ...webPreferences
- }
- });
- w.loadURL(`${serverUrl}/base-page-security.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('Disabled webSecurity');
- });
- it('should warn about insecure Content-Security-Policy', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- enableRemoteModule: false,
- ...webPreferences
- }
- });
- useCsp = false;
- 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 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 () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- allowRunningInsecureContent: true,
- ...webPreferences
- }
- });
- w.loadURL(`${serverUrl}/base-page-security.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('allowRunningInsecureContent');
- });
- it('should warn about experimentalFeatures', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- experimentalFeatures: true,
- ...webPreferences
- }
- });
- w.loadURL(`${serverUrl}/base-page-security.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('experimentalFeatures');
- });
- it('should warn about enableBlinkFeatures', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- enableBlinkFeatures: 'my-cool-feature',
- ...webPreferences
- }
- });
- w.loadURL(`${serverUrl}/base-page-security.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('enableBlinkFeatures');
- });
- it('should warn about allowpopups', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences
- });
- w.loadURL(`${serverUrl}/webview-allowpopups.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('allowpopups');
- });
- it('should warn about insecure resources', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: { ...webPreferences }
- });
- w.loadURL(`${serverUrl}/insecure-resources.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('Insecure Resources');
- });
- it('should not warn about loading insecure-resources.html from localhost', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences
- });
- w.loadURL(`${serverUrl}/insecure-resources.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.not.include('insecure-resources.html');
- });
- ifit(features.isRemoteModuleEnabled())('should warn about enabled remote module with remote content', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: { ...webPreferences, enableRemoteModule: true }
- });
- w.loadURL(`${serverUrl}/base-page-security.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', messageContainsSecurityWarning);
- expect(message).to.include('enableRemoteModule');
- });
- ifit(features.isRemoteModuleEnabled())('should not warn about enabled remote module with remote content from localhost', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: { ...webPreferences, enableRemoteModule: true }
- });
- w.loadURL(`${serverUrl}/base-page-security-onload-message.html`);
- const [,, message] = await emittedUntil(w.webContents, 'console-message', isLoaded);
- expect(message).to.not.include('enableRemoteModule');
- });
- });
- };
- generateSpecs('without sandbox', { contextIsolation: false });
- generateSpecs('with sandbox', { sandbox: true, contextIsolation: false });
- });
|