Linux: auto-trust Firefox profiles and surface in-app cert notice#3472
Linux: auto-trust Firefox profiles and surface in-app cert notice#3472gavande1 wants to merge 8 commits into
Conversation
…in-app-cert-trust-notice-with-browser-specific
There was a problem hiding this comment.
Pull request overview
This PR extends Studio’s Linux certificate trust flow to better support Firefox by importing the Studio root CA into existing Firefox profile NSS databases and showing an in-app notice linking to manual steps when Firefox is detected.
Changes:
- Add Linux helpers to discover Firefox profile NSS DBs (
cert9.db), import the CA into them, and verify trust across all existing profiles. - Update Linux trust checks/imports to include Firefox profiles in addition to the system bundle and Chromium-family NSS DBs.
- Add a Linux-only UI notice + IPC/RTK Query wiring to detect Firefox presence and link users to Firefox-specific SSL docs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tools/common/lib/linux-trust-store.ts | Adds Firefox-profile discovery, trust verification, and CA import helpers for Linux. |
| tools/common/lib/tests/linux-trust-store.test.ts | Adds unit tests for Firefox profile DB discovery helper. |
| apps/studio/src/lib/certificate-manager.ts | Extends Linux trust verification and trust flow to include Firefox profile imports/checks. |
| apps/studio/src/lib/detect-linux-browsers.ts | Adds Linux Firefox detection (PATH + common data dirs). |
| apps/studio/src/lib/tests/detect-linux-browsers.test.ts | Adds tests for Firefox detection logic (currently has a mocking issue). |
| apps/studio/src/ipc-handlers.ts | Adds IPC handler to surface Firefox-detected status to the renderer on Linux. |
| apps/studio/src/preload.ts | Exposes new IPC method in the preload bridge. |
| apps/studio/src/stores/certificate-trust-api.ts | Adds RTK Query endpoint to fetch Firefox-detected status, tagged with CertificateTrust. |
| apps/studio/src/components/content-tab-settings.tsx | Shows a Linux-only Firefox certificate notice when cert isn’t trusted and Firefox is detected. |
| apps/studio/src/lib/get-localized-link.ts | Adds docs link key for the Linux Firefox SSL anchor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…e-with-browser-specific
📊 Performance Test ResultsComparing 98cfd90 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
ivan-ottinger
left a comment
There was a problem hiding this comment.
Thank you for your work on this PR, Rahul!
I am yet to review and test the PR fully and would like to share initial thoughts I have had so far.
| { ! isCertificateTrusted && | ||
| selectedSite.enableHttps && | ||
| linuxBrowserCertStatus?.firefoxDetected && ( | ||
| <div className="mt-1 max-w-96" data-testid="trust-cert-firefox-notice"> | ||
| <span className="text-frame-text-secondary mt-1"> | ||
| { __( | ||
| 'Firefox uses its own certificate store. If Firefox doesn’t recognize the certificate, import it manually to avoid the security warning.' | ||
| ) } | ||
| </span>{ ' ' } | ||
| <LearnHowLink docsLinksKey="docsSslLinuxFirefox" /> | ||
| </div> | ||
| ) } |
There was a problem hiding this comment.
What if we kept only the original notice we already have on trunk? Instead of adding this new one we could:
- rely on the new docs section, e.g. "If you use Firefox on Linux" to communicate potential issue to the user
- ensure the existing notice is displayed even in that very edge case where the user has Firefox installed, but haven't launched it yet.
I think that could streamline the user experience and also make the code simpler.
There was a problem hiding this comment.
Thanks Ivan, I want to push back a bit here. My biggest concern with falling back to just the existing notice is what it would take to also cover the "Firefox installed but never launched" case you mentioned. Are you comfortable with the notice being persistently visible in the settings tab? That's the part I'm most hesitant about.
The existing notice is gated on !isCertificateTrusted. On Linux that already factors in Firefox profile trust via areAllFirefoxProfilesTrustedLinux, but it's vacuously true when no profile exists — so to surface the notice in the installed-but-never-launched case, we'd have to gate it on something like isFirefoxInstalled, or make isRootCATrusted return false in that scenario. Either way, that signal doesn't auto-clear: a user who has Firefox installed (common on Ubuntu, where it ships by default) but never launches it would see the notice sitting in settings indefinitely.
To be upfront about the tradeoff: my current PR doesn't really solve that edge case either — the new Firefox notice is also gated on !isCertificateTrusted, so it stays silent until a profile actually exists. The difference is that when a profile does show up, the user gets Firefox-specific guidance instead of the generic message, and isFirefoxInstalledOnLinux is what lets us know to do that. I'd rather lean on docs for the never-launched case than make the notice permanent for everyone with Firefox preinstalled.
What I was going for overall is the closest analog to the Chrome trust-status check we already have: only surface platform-specific guidance when it's actionable. Happy to trim the supporting code if parts feel heavy — but I'd like to keep the conditional surfacing rather than collapsing it into a docs-only path. WDYT?
There was a problem hiding this comment.
Hey Rahul! 👋🏼 I created this draft PR to illustrate what I meant: #3488. Basically, there would be just one notice that would be there only when it makes sense. So if the user did not start Firefox, the notice would not be rendered.
There was a problem hiding this comment.
Thanks Ivan — your draft made this much easier to evaluate, and it landed exactly where you said it would: tested the trust-then-launch flow end-to-end on the Linux VM and the existing notice reappears on focus return as you described, then the second Trust click silently imports into the new profile.
Folded your commit into this PR as 1194d83f, so the new Firefox notice + its detection/IPC/RTK Query plumbing are all gone. Updating the PR description next to reflect the new shape. Happy to leave #3488 to you to close once you've had a chance to look.
| en: 'https://developer.wordpress.com/docs/developer-tools/studio/ssl-in-studio/', | ||
| }, | ||
| docsSslLinuxFirefox: { | ||
| en: 'https://developer.wordpress.com/docs/developer-tools/studio/ssl-in-studio/#linux-firefox', |
There was a problem hiding this comment.
In relation to https://github.com/Automattic/studio/pull/3472/changes#r3240894626 we could do https://developer.wordpress.com/docs/developer-tools/studio/ssl-in-studio/#linux.
That would lead to a new Linux heading under the Certificate Trust by platform section.
There was a problem hiding this comment.
Resolved by 1194d83f — docsSslLinuxFirefox was removed entirely. The existing notice keeps using docsSslInStudio, so the Linux subsection that lands on that page will be reachable from there.
| import path from 'node:path'; | ||
| import { findOnPath } from 'src/lib/find-on-path'; | ||
|
|
||
| export function isFirefoxInstalledOnLinux( homeDir: string = os.homedir() ): boolean { |
There was a problem hiding this comment.
I might be missing something, but from what I see, if we decide to drop that new UI notice, we could get rid of isFirefoxInstalledOnLinux and a few other code parts.
There was a problem hiding this comment.
Done in 1194d83f — isFirefoxInstalledOnLinux, detect-linux-browsers.ts and its test, the IPC handler, the preload binding, and the RTK Query endpoint are all removed.
Alternative to the new Firefox notice: rely on the existing untrusted-cert notice + refetchOnFocus (already enabled on certificateTrustApi) to surface the case where Firefox is opened after the initial Trust click and a new profile DB appears without the Studio CA. - Remove the Firefox notice in content-tab-settings - Remove isFirefoxInstalledOnLinux + detect-linux-browsers tests - Remove getLinuxBrowserCertSupportStatus IPC handler + preload binding - Remove the second RTK Query endpoint + hook - Remove docsSslLinuxFirefox (rely on docsSslInStudio) - Keep the substantive fix: importCAIntoFirefoxProfilesLinux, areAllFirefoxProfilesTrustedLinux, getLinuxFirefoxProfileDbDirs, and the composition in isRootCATrusted / trustRootCA Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e-with-browser-specific
Related issues
How AI was used in this PR
Implementation drafted with Claude Code. Tests, types, and the flow described in the testing instructions below were verified manually inside the Linux VM. @ivan-ottinger also drafted #3488 to demonstrate a simpler alternative that drops the in-app Firefox-specific notice and relies on
refetchOnFocusfor the trust-after-first-launch case; that commit has been folded into this PR.Proposed Changes
trustRootCA()on Linux to also import the Studio CA into every existing Firefox profile NSS DB (cert9.db) across apt (~/.mozilla/firefox/*.default*), Snap (~/snap/firefox/common/.mozilla/firefox/*.default*), and Flatpak (~/.var/app/org.mozilla.firefox/.mozilla/firefox/*.default*) install roots.isRootCATrusted()on Linux to also verify each existing Firefox profile contains the cert, so the existing Trust Certificate notice reappears if a profile drifts. Profiles that don't exist yet are vacuously trusted (Firefox createscert9.dbon first launch — nothing to check or import into until then).tools/common/lib/linux-trust-store.tshelpers:getLinuxFirefoxProfileDbDirs,areAllFirefoxProfilesTrustedLinux,importCAIntoFirefoxProfilesLinux. They mirror the existinggetLinuxNssDbCandidates/isCAImportedInUserNssDbsLinux/importCAIntoUserNssDbsLinuxpattern.refetchOnFocus: trueoncertificateTrustApi+setupListeners(store.dispatch)instores/index.ts. When the user launches Firefox for the first time and returns focus to Studio, the trust check re-runs, finds an untrusted new profile DB, and the existing notice + Trust Certificate button reappear. One more click silently imports into the new profile (no sudo prompt — the system bundle install short-circuits when the cert is already in/etc/ssl/certs).Testing Instructions
Run inside the Linux VM (
ssh parallels@10.211.55.3, project at/home/parallels/Desktop/studio-linux).Auto-import into existing Firefox profile
.default*profile withcert9.dbexists.certutil -d sql:$HOME/.mozilla/firefox/<id>.default-release -L -n 'WordPress Studio CA'should succeed. Repeat for the snap / flatpak profile roots if you have those installations.Firefox installed but never launched (trust-then-launch flow)
rm -rf ~/.mozilla/firefox ~/snap/firefox/common/.mozilla/firefox ~/.var/app/org.mozilla.firefox/.mozilla/firefox.Trust-state regression
certutil -d sql:$HOME/.mozilla/firefox/<id>.default-release -D -n 'WordPress Studio CA'CleanShot.2026-05-13.at.21.20.36.mp4
No regressions on macOS / Windows
Reset trusted certificate (for re-testing)
Tests
npm test -- tools/common/lib/tests/linux-trust-store.test.ts apps/studio/src/components/tests/content-tab-settings.test.tsxPre-merge Checklist