|
@@ -0,0 +1,235 @@
|
|
|
+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'
|
|
|
+
|
|
|
+import { closeWindow } from './window-helpers'
|
|
|
+import { AddressInfo } from 'net';
|
|
|
+import { emittedOnce } from './events-helpers';
|
|
|
+
|
|
|
+describe('security warnings', () => {
|
|
|
+ let server: http.Server
|
|
|
+ let w: BrowserWindow
|
|
|
+ let useCsp = true
|
|
|
+ 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 = { 'Content-Security-Policy': `script-src 'self' 'unsafe-inline'` }
|
|
|
+ response.writeHead(200, useCsp ? cspHeaders : undefined)
|
|
|
+ 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
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ w.loadURL(`${serverUrl}/base-page-security.html`)
|
|
|
+ const [,, message] = await emittedOnce(w.webContents, 'console-message')
|
|
|
+ expect(message).to.include('Node.js Integration with Remote Content')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should not warn about Node.js integration with remote content from localhost', (done) => {
|
|
|
+ w = new BrowserWindow({
|
|
|
+ show: false,
|
|
|
+ webPreferences: {
|
|
|
+ nodeIntegration: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ w.webContents.once('console-message', (e, level, message) => {
|
|
|
+ expect(message).to.not.include('Node.js Integration with Remote Content')
|
|
|
+
|
|
|
+ if (message === 'loaded') {
|
|
|
+ done()
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ w.loadURL(`${serverUrl}/base-page-security-onload-message.html`)
|
|
|
+ })
|
|
|
+
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ 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 emittedOnce(w.webContents, 'console-message')
|
|
|
+ expect(message).to.not.include('insecure-resources.html')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should warn about enabled remote module with remote content', async () => {
|
|
|
+ w = new BrowserWindow({
|
|
|
+ show: false,
|
|
|
+ webPreferences
|
|
|
+ })
|
|
|
+
|
|
|
+ w.loadURL(`${serverUrl}/base-page-security.html`)
|
|
|
+ const [,, message] = await emittedOnce(w.webContents, 'console-message')
|
|
|
+ expect(message).to.include('enableRemoteModule')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should not warn about enabled remote module with remote content from localhost', (done) => {
|
|
|
+ w = new BrowserWindow({
|
|
|
+ show: false,
|
|
|
+ webPreferences
|
|
|
+ })
|
|
|
+ w.webContents.once('console-message', (e, level, message) => {
|
|
|
+ expect(message).to.not.include('enableRemoteModule')
|
|
|
+
|
|
|
+ if (message === 'loaded') {
|
|
|
+ done()
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ w.loadURL(`${serverUrl}/base-page-security-onload-message.html`)
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ generateSpecs('without sandbox', {})
|
|
|
+ generateSpecs('with sandbox', { sandbox: true })
|
|
|
+})
|