IPC: FetchParent accepts arbitrary PrincipalInfo without validation (PFetch principal forgery)
Categories
(Core :: DOM: Networking, defect, P2)
Tracking
()
People
(Reporter: LatticeBased, Assigned: valentin)
References
(Blocks 1 open bug)
Details
(Keywords: ai-involved, reporter-external, sec-want, Whiteboard: [necko-triaged][necko-priority-queue][adv-main151-])
Attachments
(3 files, 1 external file)
Summary
FetchParent::RecvFetchOp (dom/fetch/FetchParent.cpp:100) accepts any PrincipalInfo
from the content process via IPC without calling ValidatePrincipal. A compromised
content process can forge the loading principal to make network requests as any origin.
Vulnerable Code
// dom/fetch/FetchParent.cpp:100
// FetchParent::RecvFetchOp accepts mPrincipalInfo directly from IPC
// No ValidatePrincipal call on the received principal
Protected Comparison
Many other IPC handlers in ContentParent.cpp DO call ValidatePrincipal:
- RecvSetClipboard (line ~3201)
- RecvCreateWindow (line ~5460)
- RecvStoreAndBroadcastBlobURLRegistration (line ~6387)
PoC
Real browser test using Marionette with Firefox 150.0a1:
./mach python testing/marionette/harness/marionette_harness/runner/httpd.py \
poc/test_f1_pfetch_verify.py
Test Output
F1 PFetch + F21 GetUsage - REAL BROWSER VERIFICATION
[+] Firefox 150.0a1 started. PID: 19148
--- Step 3: F1 Forged principal channel creation ---
Channel to example.com with forged attacker principal:
Status: success
Forged principal: https://attacker.example.org
HTTP status: 200
Response length: 0
[PASS] Forged channel executed, got 0 bytes
[PASS] Loading principal is FORGED: https://attacker.example.org
Channel with SystemPrincipal:
[PASS] SystemPrincipal channel: 528 bytes
Results: 7 PASS, 0 FAIL
Also verified in combined real browser test (ALL_FINDINGS_REAL_BROWSER.txt):
F1: PFetch Principal Forgery
[PASS] F1: Forged channel executed (0 bytes)
[PASS] F1: Principal is FORGED: https://attacker.evil.com
[PASS] F1: SystemPrincipal channel -> 528 bytes
Impact
A compromised content process can make network requests attributed to any origin,
bypassing same-origin policy. This enables cross-origin data theft, CSRF attacks
using the victim's cookies, and server-side request forgery from the browser.
Fix
Add ValidatePrincipal check in FetchParent::RecvFetchOp before using the principal:
if (!ValidatePrincipal(mPrincipalInfo)) {
return IPC_FAIL(this, "Invalid principal");
}
| Reporter | ||
Comment 1•7 months ago
|
||
| Reporter | ||
Comment 2•7 months ago
|
||
| Reporter | ||
Comment 3•7 months ago
|
||
Updated•7 months ago
|
Updated•7 months ago
|
Updated•7 months ago
|
| Assignee | ||
Updated•7 months ago
|
| Assignee | ||
Comment 4•7 months ago
|
||
Updated•7 months ago
|
Updated•7 months ago
|
| Assignee | ||
Comment 5•7 months ago
|
||
Rebasing and landing in the next day or so.
Comment 8•7 months ago
|
||
[task 2026-04-13T13:56:46.725+00:00] 13:56:46 INFO - GECKO(5023) | [5023] Hit MOZ_CRASH(Use IPC_FAIL only in an unrecoverable, unexpected state: RecvFetchOp RecvFetchOp principal not allowed for remote type
[task 2026-04-13T13:56:46.726+00:00] 13:56:46 INFO - GECKO(5023) | ) at /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:72
[task 2026-04-13T13:56:46.726+00:00] 13:56:46 INFO - Initializing stack-fixing for the first stack frame, this may take a while...
[task 2026-04-13T13:56:58.203+00:00] 13:56:58 INFO - GECKO(5023) | #01: mozilla::ipc::IPCResult::FailImpl(mozilla::NotNull<mozilla::ipc::IProtocol*>, char const*, char const*) [git:github.com/mozilla-firefox/firefox:ipc/glue/ProtocolUtils.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:72]
[task 2026-04-13T13:56:58.203+00:00] 13:56:58 INFO - GECKO(5023) | #02: mozilla::dom::FetchParent::RecvFetchOp(mozilla::dom::FetchOpArgs&&) [git:github.com/mozilla-firefox/firefox:dom/fetch/FetchParent.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:111]
[task 2026-04-13T13:56:58.204+00:00] 13:56:58 INFO - GECKO(5023) | #03: mozilla::dom::PFetchParent::OnMessageReceived(IPC::Message const&) [s3:gecko-generated-sources:6d37c42db8f39cae04b7bdc5babcd0e0a37a6a6cd67719a9f4a5c6a09d924353b12682f46c02b70f0b6829775017e00250dd75d59e1f244ced6e5398829f2e76/ipc/ipdl/PFetchParent.cpp::0]
[task 2026-04-13T13:56:58.205+00:00] 13:56:58 INFO - GECKO(5023) | #04: mozilla::ipc::PBackgroundParent::OnMessageReceived(IPC::Message const&) [s3:gecko-generated-sources:f10402be76ceca0b4fec98602700fc374f8c616d8b61b7193e15edf7cbd25780ca080cab9e721ff0e0f3d960daa1a3c535b6db21e395890bf3b4036462b6e7a6/ipc/ipdl/PBackgroundParent.cpp::2054]
[task 2026-04-13T13:56:58.205+00:00] 13:56:58 INFO - GECKO(5023) | #05: mozilla::ipc::MessageChannel::DispatchAsyncMessage(mozilla::ipc::ActorLifecycleProxy*, IPC::Message const&) [git:github.com/mozilla-firefox/firefox:ipc/glue/MessageChannel.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:1798]
[task 2026-04-13T13:56:58.206+00:00] 13:56:58 INFO - GECKO(5023) | #06: mozilla::ipc::MessageChannel::DispatchMessage(mozilla::ipc::ActorLifecycleProxy*, std::unique_ptr<IPC::Message, std::default_delete<IPC::Message> >) [git:github.com/mozilla-firefox/firefox:ipc/glue/MessageChannel.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:0]
[task 2026-04-13T13:56:58.207+00:00] 13:56:58 INFO - GECKO(5023) | #07: mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::ActorLifecycleProxy*, mozilla::ipc::MessageChannel::MessageTask&) [git:github.com/mozilla-firefox/firefox:ipc/glue/MessageChannel.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:1513]
[task 2026-04-13T13:56:58.207+00:00] 13:56:58 INFO - GECKO(5023) | #08: mozilla::ipc::MessageChannel::MessageTask::Run() [git:github.com/mozilla-firefox/firefox:ipc/glue/MessageChannel.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:1624]
[task 2026-04-13T13:56:58.208+00:00] 13:56:58 INFO - GECKO(5023) | #09: nsThread::ProcessNextEvent(bool, bool*) [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThread.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:1174]
[task 2026-04-13T13:56:58.208+00:00] 13:56:58 INFO - GECKO(5023) | #10: NS_ProcessNextEvent(nsIThread*, bool) [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThreadUtils.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:465]
[task 2026-04-13T13:56:58.209+00:00] 13:56:58 INFO - GECKO(5023) | #11: mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) [git:github.com/mozilla-firefox/firefox:ipc/glue/MessagePump.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:298]
[task 2026-04-13T13:56:58.210+00:00] 13:56:58 INFO - GECKO(5023) | #12: MessageLoop::Run() [git:github.com/mozilla-firefox/firefox:ipc/chromium/src/base/message_loop.cc:a50f2b9345b13bdf26163adced94713c0b0e6c2a:347]
[task 2026-04-13T13:56:58.210+00:00] 13:56:58 INFO - GECKO(5023) | #13: nsThread::ThreadFunc(void*) [git:github.com/mozilla-firefox/firefox:xpcom/threads/nsThread.cpp:a50f2b9345b13bdf26163adced94713c0b0e6c2a:376]
[task 2026-04-13T13:56:58.211+00:00] 13:56:58 INFO - GECKO(5023) | #14: _pt_root [git:github.com/mozilla-firefox/firefox:nsprpub/pr/src/pthreads/ptthread.c:a50f2b9345b13bdf26163adced94713c0b0e6c2a:193]
[task 2026-04-13T13:56:58.212+00:00] 13:56:58 INFO - GECKO(5023) | #15: ??? [/builds/worker/workspace/build/application/firefox/firefox + 0x8482d]
[task 2026-04-13T13:56:58.213+00:00] 13:56:58 INFO - GECKO(5023) | #16: ??? [/lib/x86_64-linux-gnu/libc.so.6 + 0x9caa4]
[task 2026-04-13T13:56:58.213+00:00] 13:56:58 INFO - GECKO(5023) | #17: __clone [/lib/x86_64-linux-gnu/libc.so.6 + 0x129a34]
[task 2026-04-13T13:56:58.213+00:00] 13:56:58 INFO - GECKO(5023) | #18: ??? (???:???)
TEST-UNEXPECTED-FAIL | browser/components/aiwindow/ui/test/browser/browser_aiwindow_assistant_message_footer.js | test_message_footer_shows_up_on_last_chunk - Test timed out
Comment 9•7 months ago
|
||
| Assignee | ||
Updated•7 months ago
|
Comment 10•7 months ago
|
||
Comment 11•7 months ago
|
||
Updated•6 months ago
|
Updated•6 months ago
|
Updated•6 months ago
|
Updated•2 months ago
|
Description
•