advanced-csp.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. var t = require('assert')
  2. module.exports = ({browser, extensions, popup, advanced, content}) => {
  3. before(async () => {
  4. // add origin
  5. await advanced.bringToFront()
  6. await advanced.select('.m-select', 'http')
  7. await advanced.type('[type=text]', 'localhost:3000')
  8. await advanced.click('button')
  9. // TODO: wait for https://github.com/GoogleChrome/puppeteer/pull/2289
  10. // await advanced.waitFor(() => document.querySelectorAll('.m-list li').length === 2)
  11. await advanced.waitFor(200)
  12. // expand origin
  13. if (!await advanced.evaluate(() =>
  14. document.querySelector('.m-list li:nth-of-type(2)')
  15. .classList.contains('m-exapanded')))
  16. {
  17. await advanced.click('.m-list li:nth-of-type(2)')
  18. }
  19. // disable csp
  20. if (await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  21. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  22. }
  23. // enable path matching
  24. await advanced.evaluate(() => {
  25. document.querySelector('.m-list li:nth-of-type(2) input')
  26. .value = 'csp-match-path'
  27. document.querySelector('.m-list li:nth-of-type(2) input')
  28. .dispatchEvent(new Event('keyup'))
  29. })
  30. // there is debounce timeout of 750ms in the options UI
  31. await advanced.waitFor(800)
  32. })
  33. describe('preserve state', () => {
  34. it('options page', async () => {
  35. await advanced.bringToFront()
  36. // enable csp
  37. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  38. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  39. }
  40. await advanced.reload()
  41. // TODO: wait for https://github.com/GoogleChrome/puppeteer/pull/2289
  42. // await advanced.waitFor('#options')
  43. // await advanced.waitFor(100)
  44. await advanced.waitFor(200)
  45. // expand origin
  46. await advanced.click('.m-list li:nth-of-type(2)')
  47. t.strictEqual(
  48. await advanced.evaluate(() =>
  49. document.querySelector('.m-list li:nth-of-type(2) .m-switch')
  50. .classList.contains('is-checked')
  51. ),
  52. true,
  53. 'csp checkbox should be enabled'
  54. )
  55. // disable csp
  56. if (await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  57. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  58. }
  59. await advanced.reload()
  60. // TODO: wait for https://github.com/GoogleChrome/puppeteer/pull/2289
  61. // await advanced.waitFor('#options')
  62. // await advanced.waitFor(100)
  63. await advanced.waitFor(200)
  64. // expand origin
  65. await advanced.click('.m-list li:nth-of-type(2)')
  66. t.strictEqual(
  67. await advanced.evaluate(() =>
  68. document.querySelector('.m-list li:nth-of-type(2) .m-switch')
  69. .classList.contains('is-checked')
  70. ),
  71. false,
  72. 'csp checkbox should be disabled'
  73. )
  74. })
  75. })
  76. describe('strip csp header only on matching content type or url', () => {
  77. it('non matching urls should be skipped', async () => {
  78. await advanced.bringToFront()
  79. // expand origin
  80. if (!await advanced.evaluate(() =>
  81. document.querySelector('.m-list li:nth-of-type(2)')
  82. .classList.contains('m-exapanded')))
  83. {
  84. await advanced.click('.m-list li:nth-of-type(2)')
  85. }
  86. // enable csp
  87. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  88. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  89. }
  90. // go to page serving content with strict csp
  91. await content.goto('http://localhost:3000/csp-wrong-path')
  92. await content.bringToFront()
  93. // TODO: wait for https://github.com/GoogleChrome/puppeteer/pull/2289
  94. // await content.waitFor('pre')
  95. await advanced.waitFor(200)
  96. t.strictEqual(
  97. await content.evaluate(() => {
  98. try {
  99. window.localStorage
  100. }
  101. catch (err) {
  102. return err.message.split(':')[1].trim()
  103. }
  104. }),
  105. `The document is sandboxed and lacks the 'allow-same-origin' flag.`,
  106. 'localStorage should not be accessible'
  107. )
  108. })
  109. })
  110. describe('enable csp', () => {
  111. it('webRequest.onHeadersReceived event is enabled', async () => {
  112. await advanced.bringToFront()
  113. // expand origin
  114. if (!await advanced.evaluate(() =>
  115. document.querySelector('.m-list li:nth-of-type(2)')
  116. .classList.contains('m-exapanded')))
  117. {
  118. await advanced.click('.m-list li:nth-of-type(2)')
  119. }
  120. // enable csp
  121. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  122. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  123. }
  124. // go to page serving content with strict csp
  125. await content.goto('http://localhost:3000/csp-match-path')
  126. await content.bringToFront()
  127. await content.waitFor('#_html')
  128. t.strictEqual(
  129. await content.evaluate(() =>
  130. window.localStorage.toString()
  131. ),
  132. '[object Storage]',
  133. 'localStorage should be accessible'
  134. )
  135. })
  136. })
  137. describe('disable csp', () => {
  138. it('webRequest.onHeadersReceived event is disabled', async () => {
  139. await advanced.bringToFront()
  140. // expand origin
  141. if (!await advanced.evaluate(() =>
  142. document.querySelector('.m-list li:nth-of-type(2)')
  143. .classList.contains('m-exapanded')))
  144. {
  145. await advanced.click('.m-list li:nth-of-type(2)')
  146. }
  147. // disable csp
  148. if (await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  149. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  150. }
  151. // go to page serving content with strict csp
  152. await content.goto('http://localhost:3000/csp-match-path')
  153. await content.bringToFront()
  154. // TODO: wait for https://github.com/GoogleChrome/puppeteer/pull/2289
  155. // await content.waitFor('#_html')
  156. await advanced.waitFor(200)
  157. t.strictEqual(
  158. await content.evaluate(() => {
  159. try {
  160. window.localStorage
  161. }
  162. catch (err) {
  163. return err.message.split(':')[1].trim()
  164. }
  165. }),
  166. `The document is sandboxed and lacks the 'allow-same-origin' flag.`,
  167. 'localStorage should not be accessible'
  168. )
  169. })
  170. })
  171. describe('enable csp + suspend the event page', () => {
  172. it('the tab is reloaded on event page wakeup', async () => {
  173. await advanced.bringToFront()
  174. // expand origin
  175. if (!await advanced.evaluate(() =>
  176. document.querySelector('.m-list li:nth-of-type(2)')
  177. .classList.contains('m-exapanded')))
  178. {
  179. await advanced.click('.m-list li:nth-of-type(2)')
  180. }
  181. // enable csp
  182. if (!await advanced.evaluate(() => state.origins['http://localhost:3000'].csp)) {
  183. await advanced.click('.m-list li:nth-of-type(2) .m-switch')
  184. }
  185. await extensions.bringToFront()
  186. // enable developer mode
  187. await extensions.evaluate(() => {
  188. Array.from(
  189. document.querySelector('extensions-manager').shadowRoot
  190. .querySelector('extensions-item-list').shadowRoot
  191. .querySelectorAll('extensions-item'))[0].shadowRoot
  192. .querySelector('#enable-toggle').click()
  193. })
  194. // disable the extension
  195. await extensions.evaluate(() => {
  196. Array.from(
  197. document.querySelector('extensions-manager').shadowRoot
  198. .querySelector('extensions-item-list').shadowRoot
  199. .querySelectorAll('extensions-item'))[0].shadowRoot
  200. .querySelector('#enable-toggle').click()
  201. })
  202. // check
  203. t.equal(
  204. await extensions.evaluate(() =>
  205. Array.from(
  206. document.querySelector('extensions-manager').shadowRoot
  207. .querySelector('extensions-item-list').shadowRoot
  208. .querySelectorAll('extensions-item'))[0].shadowRoot
  209. .querySelector('#inspect-views a').innerText
  210. ),
  211. 'background page (Inactive)',
  212. 'background page should be inactive'
  213. )
  214. // go to page serving content with strict csp
  215. await content.goto('http://localhost:3000/csp-match-path')
  216. await content.bringToFront()
  217. // TODO: wait for https://github.com/GoogleChrome/puppeteer/pull/2289
  218. // await content.waitFor('#_html')
  219. await content.waitFor(200)
  220. t.strictEqual(
  221. await content.evaluate(() =>
  222. window.localStorage.toString()
  223. ),
  224. '[object Storage]',
  225. 'localStorage should be accessible'
  226. )
  227. })
  228. })
  229. }