security-warnings-spec.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. const chai = require('chai')
  2. const dirtyChai = require('dirty-chai')
  3. const http = require('http')
  4. const fs = require('fs')
  5. const path = require('path')
  6. const url = require('url')
  7. const { remote } = require('electron')
  8. const { BrowserWindow } = remote
  9. const { closeWindow } = require('./window-helpers')
  10. const { expect } = chai
  11. chai.use(dirtyChai)
  12. describe('security warnings', () => {
  13. let server
  14. let w = null
  15. let useCsp = true
  16. before((done) => {
  17. // Create HTTP Server
  18. server = http.createServer((request, response) => {
  19. const uri = url.parse(request.url).pathname
  20. let filename = path.join(__dirname, './fixtures/pages', uri)
  21. fs.stat(filename, (error, stats) => {
  22. if (error) {
  23. response.writeHead(404, { 'Content-Type': 'text/plain' })
  24. response.end()
  25. return
  26. }
  27. if (stats.isDirectory()) {
  28. filename += '/index.html'
  29. }
  30. fs.readFile(filename, 'binary', (err, file) => {
  31. if (err) {
  32. response.writeHead(404, { 'Content-Type': 'text/plain' })
  33. response.end()
  34. return
  35. }
  36. const cspHeaders = { 'Content-Security-Policy': `script-src 'self' 'unsafe-inline'` }
  37. response.writeHead(200, useCsp ? cspHeaders : undefined)
  38. response.write(file, 'binary')
  39. response.end()
  40. })
  41. })
  42. }).listen(8881, () => done())
  43. })
  44. after(() => {
  45. // Close server
  46. server.close()
  47. server = null
  48. })
  49. afterEach(() => {
  50. useCsp = true
  51. return closeWindow(w).then(() => { w = null })
  52. })
  53. it('should warn about Node.js integration with remote content', (done) => {
  54. w = new BrowserWindow({
  55. show: false,
  56. webPreferences: {
  57. nodeIntegration: true
  58. }
  59. })
  60. w.webContents.once('console-message', (e, level, message) => {
  61. expect(message).to.include('Node.js Integration with Remote Content')
  62. done()
  63. })
  64. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  65. })
  66. it('should not warn about Node.js integration with remote content from localhost', (done) => {
  67. w = new BrowserWindow({
  68. show: false,
  69. webPreferences: {
  70. nodeIntegration: true
  71. }
  72. })
  73. w.webContents.once('console-message', (e, level, message) => {
  74. expect(message).to.not.include('Node.js Integration with Remote Content')
  75. if (message === 'loaded') {
  76. done()
  77. }
  78. })
  79. w.loadURL(`http://localhost:8881/base-page-security-onload-message.html`)
  80. })
  81. const generateSpecs = (description, webPreferences) => {
  82. describe(description, () => {
  83. it('should warn about disabled webSecurity', (done) => {
  84. w = new BrowserWindow({
  85. show: false,
  86. webPreferences: {
  87. webSecurity: false,
  88. ...webPreferences
  89. }
  90. })
  91. w.webContents.once('console-message', (e, level, message) => {
  92. expect(message).to.include('Disabled webSecurity')
  93. done()
  94. })
  95. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  96. })
  97. it('should warn about insecure Content-Security-Policy', (done) => {
  98. w = new BrowserWindow({
  99. show: false,
  100. webPreferences: {
  101. enableRemoteModule: false,
  102. ...webPreferences
  103. }
  104. })
  105. w.webContents.once('console-message', (e, level, message) => {
  106. expect(message).to.include('Insecure Content-Security-Policy')
  107. done()
  108. })
  109. useCsp = false
  110. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  111. })
  112. it('should warn about allowRunningInsecureContent', (done) => {
  113. w = new BrowserWindow({
  114. show: false,
  115. webPreferences: {
  116. allowRunningInsecureContent: true,
  117. ...webPreferences
  118. }
  119. })
  120. w.webContents.once('console-message', (e, level, message) => {
  121. expect(message).to.include('allowRunningInsecureContent')
  122. done()
  123. })
  124. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  125. })
  126. it('should warn about experimentalFeatures', (done) => {
  127. w = new BrowserWindow({
  128. show: false,
  129. webPreferences: {
  130. experimentalFeatures: true,
  131. ...webPreferences
  132. }
  133. })
  134. w.webContents.once('console-message', (e, level, message) => {
  135. expect(message).to.include('experimentalFeatures')
  136. done()
  137. })
  138. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  139. })
  140. it('should warn about enableBlinkFeatures', (done) => {
  141. w = new BrowserWindow({
  142. show: false,
  143. webPreferences: {
  144. enableBlinkFeatures: ['my-cool-feature'],
  145. ...webPreferences
  146. }
  147. })
  148. w.webContents.once('console-message', (e, level, message) => {
  149. expect(message).to.include('enableBlinkFeatures')
  150. done()
  151. })
  152. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  153. })
  154. it('should warn about allowpopups', (done) => {
  155. w = new BrowserWindow({
  156. show: false,
  157. webPreferences
  158. })
  159. w.webContents.once('console-message', (e, level, message) => {
  160. expect(message).to.include('allowpopups')
  161. done()
  162. })
  163. w.loadURL(`http://127.0.0.1:8881/webview-allowpopups.html`)
  164. })
  165. it('should warn about insecure resources', (done) => {
  166. w = new BrowserWindow({
  167. show: false,
  168. webPreferences
  169. })
  170. w.webContents.once('console-message', (e, level, message) => {
  171. expect(message).to.include('Insecure Resources')
  172. done()
  173. })
  174. w.loadURL(`http://127.0.0.1:8881/insecure-resources.html`)
  175. w.webContents.openDevTools()
  176. })
  177. it('should not warn about loading insecure-resources.html from localhost', (done) => {
  178. w = new BrowserWindow({
  179. show: false,
  180. webPreferences
  181. })
  182. w.webContents.once('console-message', (e, level, message) => {
  183. expect(message).to.not.include('insecure-resources.html')
  184. done()
  185. })
  186. w.loadURL(`http://localhost:8881/insecure-resources.html`)
  187. w.webContents.openDevTools()
  188. })
  189. it('should warn about enabled remote module with remote content', (done) => {
  190. w = new BrowserWindow({
  191. show: false,
  192. webPreferences
  193. })
  194. w.webContents.once('console-message', (e, level, message) => {
  195. expect(message).to.include('enableRemoteModule')
  196. done()
  197. })
  198. w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
  199. })
  200. it('should not warn about enabled remote module with remote content from localhost', (done) => {
  201. w = new BrowserWindow({
  202. show: false,
  203. webPreferences
  204. })
  205. w.webContents.once('console-message', (e, level, message) => {
  206. expect(message).to.not.include('enableRemoteModule')
  207. if (message === 'loaded') {
  208. done()
  209. }
  210. })
  211. w.loadURL(`http://localhost:8881/base-page-security-onload-message.html`)
  212. })
  213. })
  214. }
  215. generateSpecs('without sandbox', {})
  216. generateSpecs('with sandbox', { sandbox: true })
  217. })