Closed Bug 1958259 Opened 1 year ago Closed 1 year ago

"Failed to deserialize csp_b64" error

Categories

(Core :: DOM: Security, defect)

defect

Tracking

()

RESOLVED FIXED
139 Branch
Tracking Status
firefox-esr115 --- unaffected
firefox-esr128 --- unaffected
firefox137 --- wontfix
firefox138 + fixed
firefox139 + fixed

People

(Reporter: robwu, Assigned: tschuster)

References

(Regression)

Details

(Keywords: csectype-other, regression, sec-low, Whiteboard: [domsecurity-active][adv-main138-])

Attachments

(1 file, 1 obsolete file)

bug 1901492 changed the serialization format of nsCSPContext without the nsCSPContext::Read method being backwards-compatible. Consequently, after updating to Firefox 136 (or later) from a pre-136 profile, the console reported the error below.

Similarly, bug 1942306 introduces another new field in 138, so when that version reaches release, something similar will happen.

This is not the first time that sessions failed to restore properly due to missing backwards compatibility, see bug 1784045 for a prior example.

Relevant diffs:

ProcessSwitch: Failed to deserialize csp_b64 'CdntGuXUQAS/4CfOuSPZrAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAP2h0dHBzOi8vY2hhdC5tb3ppbGxhLm9yZy8jL3Jvb20vIWVhRmVUa2lTdHZyYnhqQmJ4Uzptb3ppbGxhLm9yZwAAAAAAAAAFAAAACAAAABAAAAAI/////wAAAAj/////AAAACAAAABAAAAAYAAAAJwAAABgAAAABAAAAGAAAAAEAAAAZAAAAAAAAABn/////AAAAAP////8AAAAY/////wAAABoAAAAlAQAAAAAAAAAAAGR7IjEiOnsiMCI6Imh0dHBzOi8vY2hhdC5tb3ppbGxhLm9yZy8jL3Jvb20vIWVhRmVUa2lTdHZyYnhqQmJ4Uzptb3ppbGxhLm9yZyIsIjIiOiJedXNlckNvbnRleHRJZD02In19AAAAAgAAABYAZgByAGEAbQBlAC0AYQBuAGMAZQBzAHQAbwByAHMAIAAnAHMAZQBsAGYAJwAAAAABcgBkAGUAZgBhAHUAbAB0AC0AcwByAGMAIAAnAG4AbwBuAGUAJwA7ACAAcwB0AHkAbABlAC0AcwByAGMAIAAnAHMAZQBsAGYAJwAgACcAdQBuAHMAYQBmAGUALQBpAG4AbABpAG4AZQAnADsAIABzAGMAcgBpAHAAdAAtAHMAcgBjACAAJwBzAGUAbABmACcAIAAnAHcAYQBzAG0ALQB1AG4AcwBhAGYAZQAtAGUAdgBhAGwAJwAgAGgAdAB0AHAAcwA6AC8ALwB3AHcAdwAuAHIAZQBjAGEAcAB0AGMAaABhAC4AbgBlAHQALwByAGUAYwBhAHAAdABjAGgAYQAvACAAaAB0AHQAcABzADoALwAvAHcAdwB3AC4AZwBzAHQAYQB0AGkAYwAuAGMAbwBtAC8AcgBlAGMAYQBwAHQAYwBoAGEALwA7ACAAaQBtAGcALQBzAHIAYwAgACoAIABiAGwAbwBiADoAIABkAGEAdABhADoAOwAgAGMAbwBuAG4AZQBjAHQALQBzAHIAYwAgACoAIABiAGwAbwBiADoAOwAgAGYAbwBuAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAZABhAHQAYQA6ADsAIABtAGUAZABpAGEALQBzAHIAYwAgACoAIABiAGwAbwBiADoAIABkAGEAdABhADoAOwAgAGMAaABpAGwAZAAtAHMAcgBjACAAKgAgAGIAbABvAGIAOgAgAGQAYQB0AGEAOgA7ACAAdwBvAHIAawBlAHIALQBzAHIAYwAgACcAcwBlAGwAZgAnACAAYgBsAG8AYgA6ADsAIABmAHIAYQBtAGUALQBzAHIAYwAgACoAIABiAGwAbwBiADoAIABkAGEAdABhADoAOwAgAGYAbwByAG0ALQBhAGMAdABpAG8AbgAgACcAcwBlAGwAZgAnADsAIABtAGEAbgBpAGYAZQBzAHQALQBzAHIAYwAgACcAcwBlAGwAZgAnAAE=' [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISerializationHelper.deserializeObject]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: resource://gre/modules/E10SUtils.sys.mjs :: deserializeCSP :: line 325" data: no]

stack (from Firefox 137.0)

deserializeCSP resource://gre/modules/E10SUtils.sys.mjs:329
deserializeEntry resource://gre/modules/sessionstore/SessionHistory.sys.mjs:585
restore resource://gre/modules/sessionstore/SessionHistory.sys.mjs:384
restoreFromParent resource://gre/modules/sessionstore/SessionHistory.sys.mjs:53
_restoreHistory resource:///modules/sessionstore/SessionStore.sys.mjs:7617
_sendRestoreHistory resource:///modules/sessionstore/SessionStore.sys.mjs:7873
restoreTab resource:///modules/sessionstore/SessionStore.sys.mjs:6083
restoreTabs resource:///modules/sessionstore/SessionStore.sys.mjs:5931
ssi_restoreWindow resource:///modules/sessionstore/SessionStore.sys.mjs:5683
_restoreWindowsFeaturesAndTabs resource:///modules/sessionstore/SessionStore.sys.mjs:5769
_restoreWindowsInReversedZOrder resource:///modules/sessionstore/SessionStore.sys.mjs:5793
ssi_restoreWindows resource:///modules/sessionstore/SessionStore.sys.mjs:5869

Oh this is bad. Sorry, I didn't consider that we would be using this serialization format across different build ids. I think we should back out bug 1942306 for now, so we at least don't repeat this issue when 138 ships? I am definitely going to add a warning to this code so we don't forget about this again

bug 1942306 changed the serialization format of nsCSPContext without the nsCSPContext::Read method being backwards-compatible.

Do you mean 136 and bug 1901492? https://phabricator.services.mozilla.com/D233636

After scrolling up I just saw that you actually linked bug 1901492 as regressed by.

Assignee: nobody → tschuster

[Tracking Requested - why for this release]: Broken session restore. I added a backout patch to bug 1942306.

We also really need to add a test that ensures we don't break deserialization of older CSP data.

Rob, do you know if we can still restore the session even with this error or is it completely broken?

Flags: needinfo?(rob)

Ah, we seem to catch the error here and return null when the CSP fails to de-serialize. I think this means we probably don't completely break the session history for our users. We still shouldn't be doing this.

(In reply to Tom Schuster from comment #2)

After scrolling up I just saw that you actually linked bug 1901492 as regressed by.

Both bugs are prone to this issue. I found both bugs because I looked in Searchfox for the relevant deserializer, as follows:

  1. echo CdntGuXUQAS/4CfOuSPZrA | base64 -d | xxd -> 09d9 ed1a e5d4 4004 bfe0 27ce b923 d9a
  2. Search in Searchfox for the ID definition: https://searchfox.org/mozilla-central/search?q=09d9ed1a, which points to dom/security/nsCSPContext.h.
  3. Go to the source file associated with the header and look for the Read method implementation -> nsCSPContext::Read.

(In reply to Tom Schuster from comment #5)

Rob, do you know if we can still restore the session even with this error or is it completely broken?

The tabs did appear to restore. I did not check if the CSP is lost (based on the property, that would be my expectation).
The console has 50+ errors (I stopped counting after 50, I guess that it could be even 100+ from some of my many tabs).

Coincidentally I have a backup of the profile, so let me know if you want me to test anything more.

Flags: needinfo?(rob)
Group: dom-core-security

I am making this a security bug, because it technically prevents certain CSPs from being applied to websites loaded from the session history.

Attachment #9476940 - Attachment is obsolete: true

If we still do normal CSP when we reload the tabs (from headers and <meta> tags) this would hardly ever be a practical security problem:

  • you have a site attack frustrated by CSP
  • your attack has enough control to open a document only protected by an inherited policy, so you can try a CSP or sandbox escape
  • you know the victim is on a version before a serialization breakage
  • you believe they have that update staged so it will be applied on restart
  • you have a parent-crashing bug

Can we call this sec-low? (clear or change the keyword if you disagree)

Severity: -- → S3
Whiteboard: [domsecurity-active]

The bug is marked as tracked for firefox138 (beta) and tracked for firefox139 (nightly). However, the bug still has low severity.

:freddy, could you please increase the severity for this tracked bug? If you disagree with the tracking decision, please talk with the release managers.

For more information, please visit BugBot documentation.

Flags: needinfo?(fbraun)

I think we only ever deserialize nsCSPContext with E10SUtils.deserializeCSP, which means the CSP is the only data being deserialized. This makes it easier to ensure we detected the right format by making sure all data was consumed.

Attachment #9477463 - Attachment description: WIP: Bug 1958259 - Deserialize all versions of the CSP data format → Bug 1958259 - Deserialize all versions of the CSP data format. r?smaug!,robwu
Depends on: 1959034

Tom, please confirm the foundational assumption I make in comment 10: that even if we fail to deserialize CSP on restore, restoring the page will freshly apply CSP found in headers and <meta> tags.

This bug is worse if restore says "we have a restored CSP, we can save time by skipping normal CSP". That seems unlikely—especially since the page might not be in the cache—but it's not unimaginable as a performance enhancement for restoring cached pages.

Flags: needinfo?(tschuster)

Yes, I think your assumption is correct. The CSP stored in the session history seems to be what the page that was stored inherited from a previous page. We get a test failure in browser/components/sessionstore/test/browser_911547.js after disabling the CSP serialization, because we don't inherit the CSP into a data: document after restoring it. (However we don't support top level data: documents anymore, so probably not the best example)

I am not really aware of any code that would skip applying headers or <meta> tags. To be honest I am not sure where the document comes from in the session restore case, but I assume it's the normal network cache?

Flags: needinfo?(tschuster)

Addendum: I did also manually verify that a <meta> CSP still applies even after disabling the E10SUtils.serializeCSP function and reloading a closed tab.

The CSPContext (de)serialization logic and its use in session restore was originally added to counter CSP bypass in data URLs (bug 911547).

Top-level data URLs cannot be opened by web pages any more by default, unless security.data_uri.block_toplevel_data_uri_navigations is set to true.

When thinking about impact, we'd have to look for URLs and documents that may have their CSP derived elsewhere. Maybe blob:-urls (do they even persist across restarts?) or about:blank (when scripted by an opener)?

Would it apply to http(s) when opened from a page with CSP sandbox or iframe sandbox lacking the allow-popups-to-escape-sandbox value? Or is that already encoded someplace else?

Maybe blob:-urls (do they even persist across restarts?)

blob: URLs are not persisted.

about:blank (when scripted by an opener)?

We don't actually seem to be able to restore about:blank pages. When restoring we just seem to load the original document that opened the about:blank page.

Would it apply to http(s) when opened from a page with CSP sandbox or iframe sandbox lacking the allow-popups-to-escape-sandbox value? Or is that already encoded someplace else?

Sandbox properties are inherited via the sandbox flags.

Pushed by tschuster@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/88fac50d9ee9 Deserialize all versions of the CSP data format. r=smaug

Backed out for causing build bustages @ nsCSPContext.cpp

[task 2025-04-09T12:55:53.027Z] 12:55:53    ERROR -  /builds/worker/checkouts/gecko/dom/security/nsCSPContext.cpp:2148:8: error: use of undeclared identifier 'NS_ConsumeStream'
[task 2025-04-09T12:55:53.028Z] 12:55:53     INFO -   2148 |   rv = NS_ConsumeStream(aStream, UINT32_MAX, data);
[task 2025-04-09T12:55:53.028Z] 12:55:53     INFO -        |        ^
[task 2025-04-09T12:55:53.028Z] 12:55:53     INFO -  1 error generated.
Flags: needinfo?(tschuster)
Pushed by tschuster@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/9f0983d06c51 Deserialize all versions of the CSP data format. r=smaug
Flags: needinfo?(tschuster)
Group: dom-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 139 Branch

The patch landed in nightly and beta is affected.
:tschuster, is this bug important enough to require an uplift?

  • If yes, please nominate the patch for beta approval.
  • If no, please set status-firefox138 to wontfix.

For more information, please visit BugBot documentation.

Flags: needinfo?(tschuster)

Comment on attachment 9477463 [details]
Bug 1958259 - Deserialize all versions of the CSP data format. r?smaug!,robwu

Beta/Release Uplift Approval Request

  • User impact if declined/Reason for urgency: Minor security issues caused by missing CSP on session restore. But we really want to land this so that the second session restore data format breaking change from bug 1942306 doesn't reach release.
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Medium
  • Why is the change risky/not risky? (and alternatives if risky): This is quite complicated code that tries to detect the right data format by speculative parsing. We don't really have good test coverage of cross-update session restore behavior, but we at least test the serialization/de-serialization itself now.
  • String changes made/needed:
  • Is Android affected?: Yes
Flags: needinfo?(tschuster)
Attachment #9477463 - Flags: approval-mozilla-beta?

Comment on attachment 9477463 [details]
Bug 1958259 - Deserialize all versions of the CSP data format. r?smaug!,robwu

Approved for 138.0b6

Attachment #9477463 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify-
Flags: needinfo?(fbraun)
Whiteboard: [domsecurity-active] → [domsecurity-active][adv-main138-]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: