Crash in nsDocShell::PerformTrustedTypesPreNavigationCheck on javascript: link click in about:blank tabs without policy container (follow-up to bug 2003517)
Categories
(Core :: DOM: Security, defect)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox161 | --- | fixed |
People
(Reporter: europolwantme, Assigned: freddy, NeedInfo)
References
Details
(Keywords: csectype-nullptr, reporter-external, Whiteboard: [nosec][deduped])
Attachments
(1 file, 2 external files)
|
6.62 KB,
application/x-zip-compressed
|
Details |
Steps to reproduce
Environment: Firefox Nightly 159.0a1 (mozilla-central, linux-x86_64, build 2026-10-02, ftp.mozilla.org/pub/firefox/nightly/latest-mozilla-central). Deterministic: 18/18 crashing runs across multiple harness variants. Firefox ESR 140.15.0 is not affected (no Trusted Types code). Harness: selenium 4.31 + geckodriver 0.37.1 under WSL2/Kali, gdb for the crash stack.
Manual steps:
- Settings -> New Tab page: disable the New Tab page (pref
browser.newtabpage.enabled=false), so new tabs openabout:blank- a supported user setting. - Open a new tab (Ctrl+T) - a blank page appears.
- Open the DevTools console on that tab and evaluate:
document.body.innerHTML = '<a id="l" href="javascript:void(0)">x</a>';
document.getElementById('l').click();
- The content process crashes.
Both trusted input (WebDriver ElementClick) and script-initiated element.click() reproduce it - the Trusted Types check runs in DoURILoad before any user-activation gating. The same crash occurs in automation-created blank tabs (Marionette/WebDriver/Playwright startup tabs); a standalone Selenium reproducer is attached.
Controls that do NOT crash on this build:
- The bug 2003517 repro
window.open('javascript:...')- opens a blank tab, no crash (the RecvConstructBrowser fix works for that path). about:blankcreated by typing in the URL bar - script executes normally (document gets a policy container).http:,data:,blob:documents andabout:blankpopups/iframes inheriting a web origin - script executes normally.https:link clicks in the affected documents - navigate normally (the check only runs for the javascript: scheme).target=_blankactivation of a javascript: link - opens a blank tab, no crash.- Firefox ESR 140.15.0 - script executes normally.
Actual results
The content process dies with SIGSEGV (deterministic). Parent-process log (independent runs):
A content process crashed and MOZ_CRASHREPORTER_SHUTDOWN is set, shutting down
[Parent 25316, IPC I/O Parent] WARNING: process 25455 exited on signal 11: file checkouts/gecko/ipc/chromium/src/chrome/common/process_watcher_posix_sigchld.cc:161
[Parent 29339, IPC I/O Parent] WARNING: process 29475 exited on signal 11: ... (clean env)
[Parent 35258, IPC I/O Parent] WARNING: process 35401 exited on signal 11: ... (NTP-disabled new tab)
Crash stack (gdb attached to the live content process):
#0 nsDocShell::PerformTrustedTypesPreNavigationCheck(nsDocShellLoadState*, nsGlobalWindowInner*) const+95
#1 nsDocShell::InternalLoad(nsDocShellLoadState*, mozilla::Maybe<unsigned int>)+...
#2 nsDocShell::OnLinkClickSync(nsIContent*, nsDocShellLoadState*, bool, nsIPrincipal*)+...
#3 OnLinkClickEvent::Run()+...
#4 mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(...)
Faulting sequence in the function (x/10i $rip-24): call *0x8(%rax) with rax=0 (virtual call through a null-derived object).
Root cause - docshell/base/nsDocShell.cpp (current mozilla-central), still unguarded:
nsresult nsDocShell::PerformTrustedTypesPreNavigationCheck(
nsDocShellLoadState* aLoadState, nsGlobalWindowInner* aWindow) const {
MOZ_ASSERT(aWindow);
RefPtr<nsIContentSecurityPolicy> csp = aWindow->GetCsp();
if (csp->GetRequireTrustedTypesForDirectiveState() == // <-- csp can be nullptr
RequireTrustedTypesForDirectiveState::NONE) {
return NS_OK;
}
nsGlobalWindowInner::GetCsp() returns nullptr when the document has no CSP and no CSP snapshot exists (dom/base/nsGlobalWindowInner.cpp: if (mDoc) return mDoc->GetCsp(); ... return nullptr;). The caller (DoURILoad) invokes the check for every javascript:-scheme navigation when dom.security.trusted_types.enabled is on (default), without validating the CSP. A document without a CSP cannot have a require-trusted-types-for directive.
Relation to earlier bugs: bug 2003517 (same crash signature, repro window.open('javascript:...')) was fixed via bug 2002654 (Initialize policy container in RecvConstructBrowser, rev 72d46d7cb80e). That fix covers initial about:blank documents created via RecvConstructBrowser only. The documents in this report are created by navigating to about:blank (new-tab / openTrustedLinkIn flows with a system triggering principal, and automation startup tabs); those loads evidently still produce documents with no policy container, and the crashing function still has no defensive null check. The original 2003517 repro no longer crashes on this build - verified.
Impact: deterministic content-process crash (virtual call through a null pointer) in a navigation security check, reachable with one link click in the affected document class; no privileges required, activation not required beyond the click. The affected documents come from a supported user configuration (new tabs with the NTP disabled) and mainstream automation stacks (Marionette/WebDriver/Playwright) - the same impact class that made bug 2003517 actionable. The vulnerable code is enabled by default (Trusted Types) and would ride to release.
Expected results
No crash. The javascript: URL should be evaluated or ignored exactly like it is on http:/data:/blob: documents, on URL-bar-created about:blank tabs, and on Firefox ESR 140.15.0.
Suggested fix
- Harden the function (the generic fix originally attempted in bug 2002654 but scoped down to RecvConstructBrowser):
RefPtr<nsIContentSecurityPolicy> csp = aWindow->GetCsp();
if (!csp ||
csp->GetRequireTrustedTypesForDirectiveState() ==
RequireTrustedTypesForDirectiveState::NONE) {
return NS_OK;
}
(plus a release-build guard for aWindow; MOZ_ASSERT is debug-only)
- Audit the remaining about:blank creation paths (
gBrowser.addTab/openTrustedLinkIn/ automation startup tabs) for missing policy containers.
Attachments on this bug: attach-poc-manual.txt (manual repro), attach-poc-automated.py (standalone Selenium reproducer), attach-crash-stack.txt (symbolized gdb stack + disassembly), attach-crash-log.txt (SIGSEGV log excerpts), attach-differential.txt (control matrix incl. the fixed 2003517 repro).
Updated•1 month ago
|
Comment 1•1 month ago
|
||
Automatic triage (under development): sec-rating
No validation or verification has been performed.
Security rating: nosec
nsDocShell::PerformTrustedTypesPreNavigationCheck reads the CSP from the source window's policy container. When that container is missing, the CSP pointer is null, and the code calls a method on it without checking. The result is a guaranteed null-pointer dereference, which is a safe crash with no attacker-controlled offset. It only crashes the content process. Reaching it requires a document with no policy container, such as a new-tab about:blank, plus script run through DevTools or automation; web-origin documents are not affected. A safe content-process crash is not a security issue. It should still be fixed with a null check.
Updated•1 month ago
|
Comment 3•1 month ago
|
||
The severity field is not set for this bug.
:freddy, could you have a look please?
For more information, please visit BugBot documentation.
| Assignee | ||
Comment 4•15 days ago
|
||
| Assignee | ||
Comment 5•15 days ago
|
||
Updated•15 days ago
|
Updated•15 days ago
|
Comment 8•15 days ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/407dc1de5c5e
https://hg.mozilla.org/mozilla-central/rev/dc5b8b5f46ff
Updated•4 days ago
|
Description
•