-
Notifications
You must be signed in to change notification settings - Fork 31
Add Windows client hint brands override to match header we override natively #2028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for content-scope-scripts ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Temporary Branch UpdateThe temporary branch has been updated with the latest changes. Below are the details:
Please use the above install command to update to the latest version. |
[Beta] Generated file diffTime updated: Fri, 21 Nov 2025 21:37:00 GMT Android
File has changed Apple
File has changed Chrome-mv3File has changed FirefoxFile has changed IntegrationFile has changed WindowsFile has changed |
| result.brands = newBrands; | ||
| } | ||
| return result; | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Direct modification of frozen result object
The getHighEntropyValues wrapper directly modifies the result object returned by the browser (result.brands = newBrands), which could fail if the browser returns a frozen or sealed object. The safer pattern, as demonstrated in harmful-apis.js lines 126-165, creates a new object and copies properties rather than modifying the original. This prevents potential TypeErrors in strict mode and avoids unintended side effects if the browser caches result objects.
| this.log.info('shimUserAgentDataBrands - captured original brands:', this.originalBrands.map(b => `"${b.brand}" v${b.version}`).join(', ')); | ||
| } | ||
|
|
||
| if (this.cachedBrands) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't even think we need this check do we? (and the cachedBrands prop).
shimUserAgentDataBrands is called once in init which is also called once.
| return this.originalBrands.find((brand) => { | ||
| const name = brand.brand; | ||
| // Check if it starts with "Not" or " Not" or contains special chars | ||
| return name.trim().startsWith('Not') || /[^\w\s.]/.test(name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the special chars thing finds the GREASE brand as per: https://wicg.github.io/ua-client-hints/#create-arbitrary-brands-section but it might also pick up other values. Should we add an exclusion list from the config in case we match genuine values?
I think we can remove the "not" part, it's not part of the spec and could change.
What does Windows do here with the header?
Asana Task/Github Issue: https://app.asana.com/1/137249556945/project/72649045549333/task/1208581002806545?focus=true
Description
Adding an override for our client hints brands in the JS API to match those we send in the Sec-CH-UA header and resolve breakage caused by current inconsistency between the two.
Testing Steps
Use privacy test page (duckduckgo/privacy-test-pages#356) on WebView2 build from this branch of C-S-S
OR
Manually compare Sec-Ch-Ua header brands with output of
navigator.userAgentData.brandsandnavigator.userAgentData.getHighEntropyValues(['brands'])Checklist
Please tick all that apply:
Note
Implements a Windows-only
uaChBrandsfeature to overridenavigator.userAgentData.brandswith configured values (preserving GREASE) and adds integration tests and pages to verify behavior.uaChBrandsUaChBrandsto overridenavigator.userAgentData.brandswith configuredsettings.brandsand mirror intogetHighEntropyValues(['brands']).uaChBrandsininjected/src/features.jsand enables it for thewindowsplatform.integration-test/ua-ch-brands.spec.jsand includes it in Windowsplaywright.config.js.integration-test/test-pages/ua-ch-brands/to verify brand override and early-return when brands are missing.Written by Cursor Bugbot for commit 152f3d5. This will update automatically on new commits. Configure here.