Support extracting extras from profiles and addresses - #2907
Conversation
Build Branch
Static preview entry points
QR codes (mobile preview)
Integration commandsnpm (Android / Extension): Swift Package Manager (Apple): .package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/randerson/pir-extras-open-field")git submodule (Windows): git -C submodules/content-scope-scripts fetch origin pr-releases/randerson/pir-extras-open-field
git -C submodules/content-scope-scripts checkout origin/pr-releases/randerson/pir-extras-open-fieldPin to exact commitnpm (Android / Extension): Swift Package Manager (Apple): .package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "386662f3b0546aa97812f880b8e21aed52356fa6")git submodule (Windows): git -C submodules/content-scope-scripts fetch origin pr-releases/randerson/pir-extras-open-field
git -C submodules/content-scope-scripts checkout 386662f3b0546aa97812f880b8e21aed52356fa6 |
Adds an open `extras: Record<string, string>` to extracted profiles and to each of their addresses, so capturing a new field is a config change rather than a code change. `fillForm` can then read those values back out. The immediate need is `street` and `zip` to fix PeopleFinders. Extras are omitted when empty, and absent extras are tolerated everywhere. Profile hashing strips extras and collapses addresses back to one per city/state, so capturing them never churns an existing broker identifier. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
06bee5b to
c61f13f
Compare
[Beta] Generated file diffTime updated: Tue, 28 Jul 2026 04:59:18 GMT Android
File has changed AppleFile has changed IntegrationFile has changed WindowsFile has changed |
There was a problem hiding this comment.
Stale comment
Web Compatibility Assessment
File Lines Severity Finding injected/src/features/broker-protection/**— info No browser API overrides, prototype patches, wrapper-utils/DDGProxy changes, or global modifications. All changes are confined to broker-protection extraction, aggregation, and form-fill logic — not general page injection paths. injected/src/features/broker-protection/extractors/address.js107 info extractAddressFullnow normalizes city viatitleCaseand state vianormalizeState. Output shape changes vs raw DOM text, but comparisons usematchingPair/sameCityState(case-insensitive), so address matching behavior should remain stable.injected/src/features/broker-protection/actions/extract.js433–484 info dedupeAddressesreplaces a simple city/stateMapdedup with logic that prefers richer addresses (withextras) over bare city/state duplicates. Behavioral change is scoped to broker profile aggregation.injected/src/features/broker-protection/actions/fill-form.js50–51, 88–98, 154–158 info Form fill now resolves city/state and custom extras from the selected address when flat profile keys are absent. Extends existing fillFormDOM interaction patterns; no new unbounded observers, timers, or viewport/meta manipulation.injected/integration-test/broker-protection-tests/broker-protection.spec.js+ unit tests— info Substantial integration and unit test coverage for extras extraction (text/title/href), address extras, fill-form extras lookup, and omitExtrasForHashidentifier stability.No web-compatibility warnings or errors identified.
Security Assessment
File Lines Severity Finding injected/src/features/broker-protection/actions/extract.js257 info Uses Object.prototype.hasOwnProperty.call(extractors, field)for extractor lookup — avoids pollutedhasOwnPropertyon the prototype chain. Matches existing broker-protection hygiene (isNestedCityStateSpec,normalizeState).injected/src/features/broker-protection/execute.js22–25 info fillFormreadsuserProfiledirectly frominputData(notdata()), avoidingaction.dataSourceaccidentally routing extracted profile data into the user-profile slot. Correct trust-boundary separation for native-provided vs extracted data.injected/src/features/broker-protection/extractors/profile-url.js137–151 info omitExtrasForHashstripsextrasat profile and address levels and collapses addresses to one per city/state before hashing — prevents identifier churn when extras are added. Positive for profile-matching stability.injected/src/features/broker-protection/actions/fill-form.js51, 154–158 info Page-derived extras flow into form fields via lookupValue. This follows the existing broker-protection trust model (extract broker DOM → fill opt-out forms on the same broker site). No new messaging,postMessage, or cross-origin data paths.injected/src/features/broker-protection/extractors/extra.js(new) info New source file under injected/src/is not yet listed inCORE_FILES(scripts/check-strict-core.js). Process/coding-standard gap, not a runtime security issue.No security warnings, errors, or critical findings.
Risk Level
Low Risk — Broker-protection-only changes with no API shimming, messaging transport changes, captured-globals modifications, or message-bridge boundary changes; extensive test coverage added.
Recommendations
- Process (low): Add
injected/src/features/broker-protection/extractors/extra.jstoCORE_FILESinscripts/check-strict-core.jsper strict-TypeScript policy for newinjected/src/files.- Defense-in-depth (low): Consider asserting extras values are strings in
createProfile/lookupValuebefore filling forms, sinceProfileExtrasdocuments string-only values.- No action required on API fidelity, messaging security, or config gating — changes appropriately scoped to PIR automation.
Sent by Cursor Automation: Web compat and sec
|
This PR requires a manual review and approval from a member of one of the following teams:
|
Adds a `$generated_dob$` fillForm element type that fills an `<input type="date">` with a random date of birth consistent with the age on the extracted profile, resolved through the same lookup chain as every other field. Also replaces the real-looking street addresses in the broker-protection test fixtures with obviously synthetic ones. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Injected PR Evaluation: Web Compatibility & Security
Re-assessed on synchronize (641f8462f). Scope remains broker-protection only — no browser API overrides, messaging transports, captured-globals, or message-bridge changes.
New since last review (c61f13f3): $generated_dob$ fill-form element type and generateDateOfBirth() (commit 641f8462f), with unit + integration coverage including leap-day handling.
Web Compatibility Assessment
| File | Lines | Severity | Finding |
|---|---|---|---|
fill-form.js |
131–134 | info | if (!value) treats empty string as absent, so present-but-empty optional fields are skipped rather than erroring. Intentional (see fill-form-optional-empty test); behavior change vs prior strict empty-string rejection. No general-site impact — broker opt-out forms only. |
fill-form.js |
131 | info | Falsy check also treats 0 as missing. Unlikely for PII field types; worth noting if numeric extras are ever added. |
extract.js |
446–461 | info | dedupeAddresses retains multiple same-city/state rows when extras differ (e.g. distinct streets). Downstream matching (scrapedDataMatchesUserData) correctly ignores extras per unit tests. |
address.js |
titleCase | info | extractAddressFull now title-cases city names from parse-address. sameCityState / matchingPair comparisons remain case-insensitive, so no matching regression expected. |
generators.js |
29–37 | info | generateDateOfBirth uses uncaptured Date (same pattern as existing generators). No browser API shimming; only invoked for native-configured $generated_dob$ elements on data-broker opt-out pages. |
No findings at warning or error severity for general web compatibility.
Security Assessment
| File | Lines | Severity | Finding |
|---|---|---|---|
extra.js |
(new file) | info | Not added to CORE_FILES in scripts/check-strict-core.js. Process gap per injected coding standards; no runtime security impact. |
fill-form.js |
939–940, 164–168 | info | Form values resolved from page-scraped extractedProfile + extras. Expected trust model for broker automation; native config gates which sites/actions run. No new exfiltration or messaging paths. |
execute.js |
fillForm case | info | userProfile read from inputData directly (not data()), preserving correct data-source boundary. Good hygiene. |
profile-url.js |
137–150 | info | omitExtrasForHash strips extras and collapses addresses for identifier stability. Hash dedup key is case-sensitive (${city},${state}) while runtime dedup is case-insensitive — minor inconsistency, not exploitable. |
extract.js |
801 | info | Object.prototype.hasOwnProperty.call(extractors, field) avoids prototype-pollution false positives on the extractor map. Good defensive pattern. |
No findings at warning, error, or critical severity.
Risk Level
Low Risk — Scoped to broker-protection extract/fill-form logic and tests; no changes to injected API shims, messaging security boundaries, or page-wide prototype/DOM behavior.
Recommendations
- (info) Add
injected/src/features/broker-protection/extractors/extra.jstoCORE_FILESto satisfy strict-TypeScript policy for new source files. - (info) Consider aligning
omitExtrasForHashaddress dedup withcityStateKey()lowercasing for consistency (optional; current tests pass). - (info) No additional web-compat or security blockers identified for merge from an injected-runtime perspective.
Sent by Cursor Automation: Web compat and sec


Asana Task/Github Issue: https://app.asana.com/1/137249556945/task/1216773212741748
Tech Design: https://app.asana.com/1/137249556945/project/1209121419454298/task/1216773212741757
Description
Adds support for extracting
extrasfrom profiles and addresses.This solves the immediate need to extract
.streetand.zipto fix PeopleFinders. In the medium term it gives us more flexibility when fixing rules that require filling a form with extra info from an extracted profile — capturing a new field becomes a config change rather than a code change.Extras are omitted when empty, and their absence is tolerated everywhere. Profile hashing strips extras and collapses addresses back to one per city/state, so capturing them never churns an existing broker identifier.
Also adds support for filling out a fake DOB using
$generated_dob$.Testing Steps
npm run test-int) and unit tests (npm run test-unit) cover extraction and form filling for both profile- and address-level extrasChecklist
Please tick all that apply: