Skip to content

[DON'T MERGE] feat(pir): add state-aware ZIP generation#2689

Open
madblex wants to merge 3 commits into
mainfrom
feat/pir-state-aware-zip-implementation
Open

[DON'T MERGE] feat(pir): add state-aware ZIP generation#2689
madblex wants to merge 3 commits into
mainfrom
feat/pir-state-aware-zip-implementation

Conversation

@madblex
Copy link
Copy Markdown
Contributor

@madblex madblex commented May 12, 2026

Asana: https://app.asana.com/1/137249556945/task/1214636855527575

Summary

This PR adds state-aware ZIP generation for broker protection forms, using curated city ZIP data and a state default fallback.


Note

Medium Risk
Changes form-filling behavior by making $generated_zip_code$ optionally depend on extracted profile state/city, and adds a large curated ZIP dataset which may impact bundle size and edge-case behavior across states/cities.

Overview
Broker Protection form filling can now generate state/city-aware ZIP codes: $generated_zip_code$ supports an optional useState flag to pick a real ZIP from a curated state-city-zips.json list, falling back to a state default city or a random ZIP when inputs are missing/invalid.

This also hardens property checks by introducing utils.hasOwn/getOwn (using captured globals) and migrating several hasOwnProperty usages, adds unit/integration coverage for the new ZIP behavior, and bumps the bundle size threshold in verify-artifacts.js to account for the added data.

Reviewed by Cursor Bugbot for commit 2ffe3de. Bugbot is set up for automated code reviews on this repo. Configure here.

@madblex madblex changed the title feat(pir): add state-aware ZIP generation [DRAFT] feat(pir): add state-aware ZIP generation May 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

Build Branch

Branch pr-releases/feat/pir-state-aware-zip-implementation
Commit c5f936f755
Updated May 14, 2026 at 9:07:02 AM UTC

Static preview entry points

QR codes (mobile preview)
Entry point QR code
Docs QR for docs preview
Static pages QR for static pages preview
Integration pages QR for integration pages preview

Integration commands

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#pr-releases/feat/pir-state-aware-zip-implementation

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/feat/pir-state-aware-zip-implementation")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/feat/pir-state-aware-zip-implementation
git -C submodules/content-scope-scripts checkout origin/pr-releases/feat/pir-state-aware-zip-implementation
Pin to exact commit

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#c5f936f755a4f820b45cbdb569a8608a80e5f135

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "c5f936f755a4f820b45cbdb569a8608a80e5f135")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/feat/pir-state-aware-zip-implementation
git -C submodules/content-scope-scripts checkout c5f936f755a4f820b45cbdb569a8608a80e5f135

@github-actions github-actions Bot added the semver-patch Bug fix / internal — no release needed label May 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

[Beta] Generated file diff

Time updated: Thu, 14 May 2026 09:07:42 GMT

Android
    - android/autofillImport.js
  • android/brokerProtection.js

File has changed

Apple
    - apple/contentScopeIsolated.js

File has changed

Integration
    - integration/contentScope.js

File has changed

Windows
    - windows/contentScope.js

File has changed

@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from ff7fa93 to 235a41d Compare May 12, 2026 13:35
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js:35-40 - warning: ZIP table lookups currently accept inherited properties. If the extracted/profile state is unknown, a page that has polluted Object.prototype can make the state appear present and turn the intended random-ZIP fallback into an exception or page-influenced ZIP data.

Security Assessment

  • injected/src/features/broker-protection/actions/generators.js:35-40 - warning: stateUpperCase in STATE_CITY_ZIPS and the unchecked city bracket read cross a hostile-page prototype boundary. STATE_CITY_ZIPS is a normal JSON object, so inherited properties from a tampered Object.prototype are visible during lookup.

Risk Level

Medium Risk: this is scoped to broker-protection form-fill generation and does not touch API shims, messaging, captured globals, or bridge/origin checks, but it runs in injected code over page/extracted data.

Recommendations

  • Replace inherited-property lookups with own-property checks, matching nearby patterns such as Object.prototype.hasOwnProperty.call(...), for both the state table and city/default lookup.
  • Add a unit case that pollutes Object.prototype for an unknown state/city and verifies generateZipCode() still returns a 5-digit random ZIP instead of throwing or using inherited data.

Verification run: npm run build --workspace=injected -- --platform android-broker-protection, npm run test-unit --workspace=injected -- --filter=generateZipCode, and ZIP JSON structure validation all passed.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

Comment thread injected/src/features/broker-protection/actions/generators.js Outdated
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Cursor review was not successful.

This PR requires a manual review and approval from a member of one of the following teams:

  • @duckduckgo/content-scope-scripts-owners
  • @duckduckgo/apple-devs
  • @duckduckgo/android-devs
  • @duckduckgo/team-windows-development
  • @duckduckgo/extension-owners
  • @duckduckgo/config-aor
  • @duckduckgo/breakage-aor
  • @duckduckgo/breakage

@madblex madblex marked this pull request as ready for review May 13, 2026 15:37
@madblex madblex requested review from a team as code owners May 13, 2026 15:37
@madblex madblex changed the title [DRAFT] feat(pir): add state-aware ZIP generation feat(pir): add state-aware ZIP generation May 13, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 35-40 - warning: the state table check still uses stateUpperCase in STATE_CITY_ZIPS, followed by inherited bracket reads. In an injected page context, a polluted Object.prototype can make an unknown state appear present and bypass the intended random-ZIP fallback, causing throws or page-influenced ZIP selection.

Security Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 35-40 - warning: the lookup crosses a hostile-page prototype boundary. STATE_CITY_ZIPS is imported JSON backed by ordinary objects, so inherited properties are visible to in and unchecked stateCities[...] reads when state/city data is derived from broker-page extraction or native action state.

Risk Level

Medium Risk: scoped to broker-protection form-fill generation and tests, with no API shim, messaging, captured-global, or bridge/origin changes, but the new lookup runs in injected code over potentially page-influenced profile fields.

Recommendations

  • Replace inherited-property checks with own-property checks, e.g. Object.prototype.hasOwnProperty.call(STATE_CITY_ZIPS, stateUpperCase) and own checks on stateCities before city/default lookup.
  • Add a regression test that pollutes Object.prototype for an unknown state/city and verifies generateZipCode() still returns a random 5-digit ZIP without using inherited data or throwing.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed on the current head.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@github-actions github-actions Bot added semver-minor New feature — triggers minor version bump and removed semver-patch Bug fix / internal — no release needed labels May 13, 2026
@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from bd0e851 to b4b4f3c Compare May 13, 2026 15:57
@github-actions github-actions Bot added semver-patch Bug fix / internal — no release needed and removed semver-minor New feature — triggers minor version bump labels May 13, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 32-42 - info: the current head uses own-property checks for both state and city ZIP lookups, so the previous inherited-property/prototype-pollution compatibility concern is addressed. Unknown or missing state/city values still fall back to a random 5-digit ZIP.
  • injected/unit-test/verify-artifacts.js, line 12 - info: the ZIP table raises the injected bundle-size guard from 860 KB to 890 KB. This is a scoped size/perf increase for bundles that include brokerProtection, not an API-surface or DOM-compat regression.

Security Assessment

  • No warning/error findings in the current diff. The PR does not change API shims, captured globals, message bridge checks, origin validation, postMessage, or native messaging payload construction.
  • injected/src/features/broker-protection/actions/generators.js, lines 35-42 - info: the lookup now avoids inherited JSON-object properties via hasOwn(), addressing the stale security concern from the earlier review.

Risk Level

Medium Risk: scoped to broker-protection form-fill generation over profile-derived city/state fields plus an eager ZIP dataset in injected bundles; no cross-platform API override or messaging security surface changes.

Recommendations

  • Add a small regression unit that pollutes Object.prototype and verifies generateZipCode({ state: 'ZZ', city: 'Injected' }) still returns a random 5-digit ZIP without using inherited data.
  • If bundle size becomes a concern, consider a more compact ZIP representation or platform-specific loading for brokerProtection-only contexts.

Verification: npm run test-unit --workspace injected -- --filter='generateZipCode' and npm run build --workspace injected passed on the current head.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

No new web compatibility findings. The PR stays within the existing broker-protection form-fill path, does not add API overrides/shims, and preserves the existing form value-setting behavior while only changing generated ZIP selection when useState is explicitly set.

Security Assessment

No new security findings. The previous inherited-property lookup concern is addressed by own-property checks before reading the ZIP table, and this diff does not change messaging, bridge secrets, origin checks, captured globals, or postMessage usage.

Risk Level

Medium Risk: injected broker-protection behavior now depends on a bundled state/city ZIP table and page/native-derived profile fields, but the change is scoped and avoids API surface, wrapper, messaging, or initialization changes.

Recommendations

  • No blocking recommendations.
  • Optional hardening: add a regression unit test that pollutes Object.prototype and verifies unknown state/city input still falls back to a random 5-digit ZIP.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from b4b4f3c to 98c3dbc Compare May 13, 2026 16:02
@github-actions github-actions Bot added semver-minor New feature — triggers minor version bump and removed semver-patch Bug fix / internal — no release needed labels May 13, 2026
@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch 2 times, most recently from 866ccb6 to 55577c2 Compare May 13, 2026 16:05
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/utils/utils.js, lines 241-242 - warning: the shared hasOwn() helper re-reads Object.prototype.hasOwnProperty at action time. Broker pages run in the same hostile JS environment and can patch or delete that method after injection, which can turn expected missing-field paths into throws or incorrect matches.

Security Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 35-48 / injected/src/features/broker-protection/utils/utils.js, lines 241-242 - warning: the state/city ZIP lookup now depends on hasOwn() for the prototype-pollution boundary, but hasOwn() itself uses an uncaptured global prototype method. I reproduced a page-style tamper where replacing Object.prototype.hasOwnProperty and adding an inherited ZZ entry makes generateZipCode({ state: 'ZZ' }) use the inherited ZIP instead of the random fallback.

Risk Level

Medium Risk: scoped to broker-protection form-fill generation and profile-derived ZIP selection, with no API shims, messaging, bridge, origin-validation, or load() changes, but it runs in injected code against hostile pages.

Recommendations

  • Build hasOwn() from the captured hasOwnProperty in captured-globals.js or a bound helper captured at module load, rather than reading Object.prototype.hasOwnProperty when actions execute.
  • Add a regression unit that imports generateZipCode(), tampers with Object.prototype.hasOwnProperty plus an inherited state/city entry, and verifies unknown states still fall back to a random 5-digit ZIP.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

Comment thread injected/src/features/broker-protection/utils/utils.js Outdated
@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from 55577c2 to 8e86270 Compare May 13, 2026 16:06
@github-actions github-actions Bot added semver-patch Bug fix / internal — no release needed and removed semver-minor New feature — triggers minor version bump labels May 13, 2026
@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from 8e86270 to 44c168d Compare May 13, 2026 16:09
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 34-40 - warning: state?.toUpperCase() / city?.toUpperCase() assume runtime strings. These values are carried through action/extracted-profile data, so malformed JSON/native/page-derived values such as numbers or arrays throw instead of taking the documented random/default ZIP fallback.

Security Assessment

  • injected/src/features/broker-protection/utils/utils.js, lines 241-242 - warning: the new hasOwn() helper reads live Object.prototype.hasOwnProperty. In page-world injected code, a hostile broker page can replace that prototype method after injection and make ZIP/action-data own-property checks throw or lie. captured-globals.js already snapshots hasOwnProperty; this helper should use that captured reference.

Risk Level

Medium Risk: the change is scoped to broker-protection form filling and does not touch API shims, messaging, origin validation, or bridge secrets, but it runs over action/extracted profile data in injected code.

Recommendations

  • Import hasOwnProperty from captured-globals.js in utils.js and implement hasOwn() as hasOwnProperty.call(obj, key); add a regression that tampers with Object.prototype.hasOwnProperty.
  • Normalize state and city with typeof value === 'string' ? value.toUpperCase() : undefined before ZIP lookup; add cases for non-string state/city values verifying fallback behavior.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

Comment thread injected/src/features/broker-protection/actions/generators.js Outdated
Comment thread injected/src/features/broker-protection/utils/utils.js
@github-actions github-actions Bot added semver-minor New feature — triggers minor version bump and removed semver-patch Bug fix / internal — no release needed labels May 13, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 34-40 - warning: state?.toUpperCase() and city?.toUpperCase() assume runtime strings. If malformed native/action data or page-derived extracted profile data supplies a number/array/object, ZIP generation throws before reaching the documented random/default ZIP fallback, causing the fillForm action to fail instead of preserving prior random ZIP behavior.

Security Assessment

  • No warning/error security findings in the current diff. The earlier inherited-property boundary is addressed by hasOwn() using the captured hasOwnProperty, and this PR does not change API shims, captured globals, messaging transports, bridge secrets, origin checks, or postMessage usage.

Risk Level

Medium Risk: scoped to broker-protection form filling and a bundled ZIP lookup table over profile-derived state/city fields; no API override or messaging security surface changes.

Recommendations

  • Normalize only string values before lookup, e.g. const stateUpperCase = typeof state === 'string' ? state.toUpperCase() : undefined and the same for city, so invalid values take the fallback path.
  • Add regression tests for non-string state and city values confirming generateZipCode() returns a 5-digit fallback/default ZIP instead of throwing.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed. A direct runtime probe with { state: 5 } and { state: 'IL', city: 5 } currently reproduces the TypeError.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from 44c168d to 7aea0c2 Compare May 13, 2026 16:13
@github-actions github-actions Bot added semver-patch Bug fix / internal — no release needed and removed semver-minor New feature — triggers minor version bump labels May 13, 2026
@madblex madblex requested review from brianhall and kdzwinel May 13, 2026 16:21
@madblex
Copy link
Copy Markdown
Contributor Author

madblex commented May 13, 2026

@jonathanKingston do we need your review here or will we (in PIR) be able to merge on our own?

@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from 7aea0c2 to ff85d14 Compare May 14, 2026 08:19
@github-actions github-actions Bot added semver-minor New feature — triggers minor version bump and removed semver-patch Bug fix / internal — no release needed labels May 14, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 34-40 - warning: state?.toUpperCase() and city?.toUpperCase() still assume runtime strings. These values are ultimately profile/action data, so malformed native input or page-derived extraction such as state: 5 or city: [] throws before the intended random/default ZIP fallback and aborts fillForm.

Security Assessment

  • No warning/error security findings in the current diff. The previous inherited-property/captured-hasOwnProperty concern is addressed, and this PR does not change API shims, wrapper utilities, messaging transports, bridge secret/origin checks, or postMessage usage.

Risk Level

Medium Risk: scoped to broker-protection form filling and a bundled ZIP lookup table over profile-derived state/city fields; no API override or messaging security surface changes.

Recommendations

  • Guard uppercase normalization by type, e.g. const stateUpperCase = typeof state === 'string' ? state.toUpperCase() : undefined and the same for city.
  • Add regression tests for non-string state and city values confirming generateZipCode() returns a 5-digit random/default ZIP instead of throwing.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed. A direct runtime probe with { state: 5 } and { state: 'IL', city: 5 } still reproduces the TypeError.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

*/
export function generateZipCode(params) {
const { state, city } = params ?? {};
const stateUpperCase = state?.toUpperCase();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional chaining only handles null/undefined; it still calls .toUpperCase() on any other runtime value. Since params comes from profile/action data rather than a schema check at this boundary, malformed input like { state: 5 } or { state: 'IL', city: [] } throws and aborts fillForm instead of taking the random/default ZIP fallback. Please gate both conversions with typeof value === 'string' and add non-string regression cases.

@madblex madblex force-pushed the feat/pir-state-aware-zip-implementation branch from ff85d14 to 2ffe3de Compare May 14, 2026 09:06
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Web Compatibility Assessment

  • injected/src/features/broker-protection/actions/generators.js, lines 32-42 - info: the current ZIP lookup type-checks state and city before case normalization and falls back for unknown/malformed inputs, so the prior non-string toUpperCase() fill-form abort is addressed. No API overrides, shims, prototype patches, DOM readiness changes, or event-listener timing changes are introduced.
  • injected/unit-test/verify-artifacts.js, line 11 - info: the bundle-size guard is raised to 890 KB to account for the eager ZIP table. This is a scoped parse/size increase for bundles that include brokerProtection, not an API-surface or DOM-compat regression.

Security Assessment

  • injected/src/features/broker-protection/utils/utils.js, lines 243-254 - info: hasOwn() now uses the captured hasOwnProperty, and generateZipCode() uses own-property helpers for state/city table reads, addressing the earlier prototype-pollution boundary concern.
  • No warning/error security findings. This diff does not change captured globals, message bridge checks, messaging transports, origin validation, postMessage, network requests, or native message payload construction.

Risk Level

Medium Risk: scoped to broker-protection form-fill generation over profile-derived state/city fields plus a bundled ZIP dataset; no cross-platform API override, wrapper, initialization, or messaging security surface changes.

Recommendations

  • No blocking recommendations.
  • Optional hardening: add a direct generateZipCode() regression that pollutes Object.prototype with inherited state/city ZIP entries and verifies unknown input still falls back.
  • If bundle size becomes material, consider a compact table representation or loading the ZIP data only in broker-protection-specific bundles.

Verification: npm run test-unit --workspace=injected -- --filter=generateZipCode and npm run build --workspace=injected -- --platform android-broker-protection passed on the current head.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@madblex madblex removed request for brianhall and kdzwinel May 14, 2026 10:25
@madblex madblex changed the title feat(pir): add state-aware ZIP generation [DON'T MERGE] feat(pir): add state-aware ZIP generation May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-minor New feature — triggers minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant