fix(fonts): keep the browser chrome out of the spoofed font list (#695) - #703
Open
pratyush618 wants to merge 4 commits into
Open
fix(fonts): keep the browser chrome out of the spoofed font list (#695)#703pratyush618 wants to merge 4 commits into
pratyush618 wants to merge 4 commits into
Conversation
The gfx font lookup paths need to consult the spoofed "fonts" list on every family resolution, so it cannot be re-parsed from CAMOU_CONFIG per call.
font.system.whitelist makes ApplyWhitelist() delete non-listed families from the process-wide font list, and with the shared font list that pruning happens in the parent process -- the one that paints the browser chrome. On Windows the titlebar buttons lost Segoe Fluent Icons and drew tofu boxes for U+E921/E922/E8BB. Filter on FontVisibilityProvider::IsChrome() instead, in the three content-reachable paths: FindAndAddFamiliesLocked, GlobalFontFallback and gfxUserFontSet's src: local(). Fixes daijro#695
Chrome CSS is `font: message-box`, so the browser UI was handed "Segoe UI" on Linux and "-apple-system" on Windows -- families that aren't installed, leaving the toolbar in the default serif font. The GTK and cocoa LookAndFeel hooks are dropped: with the ComputeSystemFont guard they are only reachable when navigator.platform is unspoofed (no-op) or the document is chrome (harmful). Refs daijro#695
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #695.
Root cause
Two independent bugs, both "spoofing leaks into the browser's own chrome UI".
1. Tofu titlebar buttons
The boxes in the report are
U+E921/U+E922/U+E8BB— Firefox's Windows titlebar glyphs:font-hijacker.patchfed the spoofedfontslist into Firefox'sfont.system.whitelistpref. That pref drivesgfxPlatformFontList::ApplyWhitelist(), which removes every non-listed family from the font list — and with the shared font list (default on all three platforms) that pruning runs in the parent process, i.e. the process that paints the chrome.Neither icon font is in any generated mask, and
Segoe UIonly survives when the spoofed OS is Windows. Linux hosts are insulated by the bundledFONTCONFIG_FILE, which is why this only shows up on Windows and macOS builds.2. Serif toolbar
font-system-fonts-css2.patchhookednsLayoutUtils::ComputeSystemFontfor every document whenevernavigator.platformis spoofed. Chrome CSS isfont: message-box, so the browser UI was handed"Segoe UI"on Linux /"-apple-system"on Windows — families that aren't installed → fallback to the default serif font.system-ui-font-spoofing.patchhad the same problem for thesystem-uigeneric.Fix
additions/camoucfg/MaskConfig.hppFontAllowlist()/HasFontAllowlist()/IsFontAllowed(), parsed once per process — the gfx paths consult this on every family resolutionpatches/font-hijacker.patchfont.system.whitelist. Filter at lookup time onFontVisibilityProvider::IsChrome(), across all three content-reachable pathspatches/font-system-fonts-css2.patchpatches/system-ui-font-spoofing.patchThe three content-reachable font paths now covered by the lookup-time filter:
FindAndAddFamiliesLocked—font-family/ CSS generic resolution, i.e. whatdocument.fonts.check()and text-metric probing go through.GlobalFontFallback— per-character system fallback. The cmap path stays forced (as the whitelist did), so the platform fallback APIs can't pick a family behind our back.gfxUserFontSetsrc: local()— upstream already refuseslocal()sources while a whitelist is active; that behaviour is kept for content under the mask, so a page can't probe for hidden families.font-system-fonts-css2.patchalso drops its GTKnsLookAndFeel::PerThemeData::GetFontand cocoagfxMacPlatformFontList::LookupSystemFonthooks. With theComputeSystemFontguard in place they are reachable only when the spoof branch is not taken — which is exactly whennavigator.platformis unspoofed (where they were no-ops) or when the document is chrome (where they broke the UI).Behaviour for web content is unchanged
src: local()probing stays blocked.getComputedStyle().fontFamilyfor the CSS2 keywords andsystem-uireturns the same spoofed values (CreepJS attribution unchanged).IsChrome()is Firefox's own notion of privileged (Document::IsInChromeDocShell()), the same predicateFontVisibilityProvider::ComputeFontVisibility()uses for its "chrome gets User level" rule — soabout:pages are still treated as content, as upstream does.Testing
anti-font-fingerprinting→font-hijacker→font-list-spoofing→font-system-fonts-css2→system-ui-font-spoofing) applies to pristine Firefox 152.0.4 with zero rejects. Verified in particular thatfont-hijacker's newFindAndAddFamiliesLockedhunk andfont-list-spoofing's per-user-context hunk coexist in that function.MaskConfighelpers compile under-std=c++20 -Wall -Wextraand were unit-tested against a realCAMOU_CONFIGpayload.build-tester'scssFingerprint.systemFontsandfontAvailabilitychecks run in content, so they are unaffected by the chrome exemption.I do not have a full build in this environment — the C++ is written and reviewed against the real FF152 sources but has not been compiled in-tree. Happy to iterate if CI turns up anything.
Two adjacent issues found, deliberately left alone
Segoe Fluent Icons/Segoe MDL2 Assetsare non-essential in_ESSENTIAL_FONTS_WINDOWS(pythonlib/camoufox/fingerprints.py), so a Windows profile randomly claims not to have fonts that ship on every real Windows install — a weak tell. Would have masked this bug too, but it's a separate change.GetSpoofedSystemFontForRFP's fall-through for a Linux spoof is#if defined(XP_WIN)/XP_MACOSXetc., so a Linux fingerprint on a Windows host reportsSegoe UIrather thansans-serif.