Skip to content

fix: widen isSafeDynamicKey parameter type to PropertyKey - #9774

Open
ZayanKhan-12 wants to merge 2 commits into
MetaMask:mainfrom
ZayanKhan-12:fix/utils-200-widen-issafedynamickey
Open

fix: widen isSafeDynamicKey parameter type to PropertyKey#9774
ZayanKhan-12 wants to merge 2 commits into
MetaMask:mainfrom
ZayanKhan-12:fix/utils-200-widen-issafedynamickey

Conversation

@ZayanKhan-12

@ZayanKhan-12 ZayanKhan-12 commented Aug 4, 2026

Copy link
Copy Markdown

Explanation

isSafeDynamicKey in @metamask/controller-utils only accepts string keys and returns false for any non-string input. This means valid dynamic keys of type number (e.g. array indices such as currentIndex in SmartTransactionsController, the case that motivated the ticket) or symbol cannot be validated without a lossy String() conversion.

Neither number nor symbol keys can be used for a prototype pollution attack via the blocklisted keys:

  • number keys are coerced to canonical numeric strings when used as property keys, which can never collide with '__proto__', 'constructor', or 'prototype';
  • symbol keys cannot alias the string-keyed Object.prototype properties.

This PR widens the parameter type to PropertyKey (string | number | symbol). Behavior:

  • string keys: unchanged — checked against PROTOTYPE_POLLUTION_BLOCKLIST.
  • number / symbol keys: now return true (previously false).
  • Non-PropertyKey runtime values passed from untyped code (e.g. null, undefined): still return false, preserving the existing defensive behavior.

The change is backwards compatible for all existing (string-typed) callers.

Note: the tracking issue lives in the MetaMask/utils repo, but the function itself lives here in @metamask/controller-utils (added in #4041), so this PR targets core.

References

Fixes MetaMask/utils#200

Testing

  • yarn workspace @metamask/controller-utils run jest --no-coverage — 6 suites, 186 tests passed
  • yarn workspace @metamask/controller-utils run test (with coverage) — passed
  • yarn workspace @metamask/controller-utils run build — passed
  • yarn eslint on the changed files — clean
  • Added test coverage for all three PropertyKey subtypes (blocklisted and safe strings, number keys incl. NaN, symbol keys incl. Symbol('__proto__')) plus null/undefined returning false

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

🤖 Generated with Claude Code


Note

Low Risk
Small, intentional behavior change in a prototype-pollution helper; string semantics are unchanged and the new number/symbol paths are documented as non-polluting.

Overview
isSafeDynamicKey in @metamask/controller-utils now accepts PropertyKey (string | number | symbol) instead of only string, so callers can validate numeric indices and symbol keys without coercing to strings.

String keys still use PROTOTYPE_POLLUTION_BLOCKLIST as before. Number and symbol keys now return true (they were false for any non-string). null / undefined still return false. JSDoc explains why number/symbol keys are treated as safe; tests and the package changelog are updated.

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

`isSafeDynamicKey` only accepted `string` keys and returned `false` for
any non-string input, so valid dynamic keys of type `number` (e.g. array
indices such as `currentIndex` in SmartTransactionsController) or
`symbol` could not be validated without a lossy `String()` conversion.

Number and symbol keys cannot be used for prototype pollution via the
blocklisted string keys: numbers coerce to numeric strings that never
collide with the blocklist, and symbol keys cannot alias string-keyed
`Object.prototype` properties. The function now accepts any
`PropertyKey`, keeps the blocklist check for strings, and still returns
`false` for non-`PropertyKey` runtime values passed from untyped code.

Fixes MetaMask/utils#200

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ZayanKhan-12
ZayanKhan-12 requested a review from a team as a code owner August 4, 2026 01:04
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Widen isSafeDynamicKey parameter type from string to PropertyKey

1 participant