browser_csp_policy_container_migration.js (3852B)
1 "use strict"; 2 3 // We use data URL because CSP_ShouldURIInheritCSP requires the URL to be 4 // about:blank, abour:srcdoc, or be a blob, filesystem, data, or javascript scheme. 5 const URL = `data:text/html,<html><body> <span id="change_me">Original</span> <script> document.getElementById("change_me").textContent = "Modified"; </script></body></html>`; 6 7 const CSP_JSON = `{"csp-policies":[{"default-src":["'self'"],"report-only":false}]}`; 8 9 const CSP_SERIALIZED = 10 "CdntGuXUQAS/4CfOuSPZrAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAKmh0dHBzOi8vYi5jb21wYXNzLWRlbW8uY29tL2NzcF9wbGF5Z3JvdW5kLwAAAAAAAAAFAAAACAAAABIAAAAI/////wAAAAj/////AAAACAAAABIAAAAaAAAAEAAAABoAAAAQAAAAGgAAABAAAAAqAAAAAAAAACr/////AAAAAP////8AAAAa/////wAAABr/////AQAAAAAAAAAAADh7IjEiOnsiMCI6Imh0dHBzOi8vYi5jb21wYXNzLWRlbW8uY29tL2NzcF9wbGF5Z3JvdW5kLyJ9fQAAAAEAAAASAGQAZQBmAGEAdQBsAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnAAAA"; 11 12 // Same CSP, but serialized as a policy container 13 const POLICY_CONTAINER_SERIALIZED = 14 "ydqGXsPXSqGicQ9XHwE8MAAAAAAAAAAAwAAAAAAAAEYAAAABAQnZ7Rrl1EAEv+Anzrkj2awdYyAIbJdIrqUcFuLaoPT2Ad6UctCANBHTk5kAEEug/UCSBzpUbXhPMJE6uHGBMgjGAAAAAv////8AAAG7AQAAACpodHRwczovL2IuY29tcGFzcy1kZW1vLmNvbS9jc3BfcGxheWdyb3VuZC8AAAAAAAAABQAAAAgAAAASAAAACP////8AAAAI/////wAAAAgAAAASAAAAGgAAABAAAAAaAAAAEAAAABoAAAAQAAAAKgAAAAAAAAAq/////wAAAAD/////AAAAGv////8AAAAa/////wEAAAAAAAAAAAA4eyIxIjp7IjAiOiJodHRwczovL2IuY29tcGFzcy1kZW1vLmNvbS9jc3BfcGxheWdyb3VuZC8ifX0AAAABAAAAEgBkAGUAZgBhAHUAbAB0AC0AcwByAGMAIAAnAHMAZQBsAGYAJwAAAAFIEv8yG/9CO5f8QKVpba0iSBL/Mhv/QjuX/EClaW2tIgAAAAEAAA=="; 15 16 /* 17 * Tests that whether we pass a serialized CSP or policy container 18 * to the session store, it gets deserialized correctly and restored 19 * in the tab state. 20 */ 21 add_task(async function () { 22 // Sanity check: ensure that the CSP JSON and serialized CSP match 23 is( 24 E10SUtils.deserializeCSP(CSP_SERIALIZED).toJSON(), 25 CSP_JSON, 26 "CSP should deserialize correctly from serialized CSP string" 27 ); 28 29 // Sanity check 30 await checkScriptRunsWithoutCSP({ 31 url: URL, 32 }); 33 34 // Firefox 142 and earlier writes entry.csp; 35 await checkCSPWithSessionHistoryEntry({ url: URL, csp: CSP_SERIALIZED }); 36 // Firefox 143 and later writes to policyContainer (bug 1974070). 37 await checkCSPWithSessionHistoryEntry({ 38 url: URL, 39 policyContainer: POLICY_CONTAINER_SERIALIZED, 40 }); 41 }); 42 43 async function checkCSPWithSessionHistoryEntry(entry) { 44 // Create session history entry with `csp` property 45 const tab = await createTabWithSessionHistoryEntry(entry); 46 47 // check that the inline script is blocked 48 is(await didScriptRun(tab.linkedBrowser), false); 49 50 is( 51 tab.linkedBrowser.policyContainer.csp.toJSON(), 52 CSP_JSON, 53 "CSP should be restored correctly from session history entry" 54 ); 55 56 // cleanup 57 BrowserTestUtils.removeTab(tab); 58 } 59 60 async function checkScriptRunsWithoutCSP(entry) { 61 // Create session history entry without `csp` property 62 const tab = await createTabWithSessionHistoryEntry(entry); 63 64 // check that the inline script runs 65 is(await didScriptRun(tab.linkedBrowser), true); 66 67 is( 68 tab.linkedBrowser.policyContainer.csp.toJSON(), 69 `{"csp-policies":[]}`, 70 "CSP should not be restored when not present in session history entry" 71 ); 72 73 // cleanup 74 BrowserTestUtils.removeTab(tab); 75 } 76 77 async function createTabWithSessionHistoryEntry(entry) { 78 const state = { 79 entries: [entry], 80 }; 81 82 // create a new tab 83 const tab = BrowserTestUtils.addTab(gBrowser); 84 85 // set the tab's state 86 ss.setTabState(tab, JSON.stringify(state)); 87 88 // wait for the tab to be loaded 89 await promiseBrowserLoaded(tab.linkedBrowser); 90 91 return tab; 92 } 93 94 function didScriptRun(browser) { 95 return SpecialPowers.spawn(browser, [], function () { 96 return ( 97 content.document.getElementById("change_me").innerText === "Modified" 98 ); 99 }); 100 }