Skip to content

fix(core-base): key paths containing javascript built-ins are handled inconsistently#2403

Merged
kazupon merged 2 commits into
masterfrom
fix/1838
Feb 25, 2026
Merged

fix(core-base): key paths containing javascript built-ins are handled inconsistently#2403
kazupon merged 2 commits into
masterfrom
fix/1838

Conversation

@kazupon
Copy link
Copy Markdown
Member

@kazupon kazupon commented Feb 25, 2026

resolve #1838

related #2098

Summary by CodeRabbit

  • Bug Fixes

    • Improved property resolution to safely handle built-in object property names in key paths, returning null when a property is absent to prevent unexpected access errors.
  • Tests

    • Added thorough tests covering resolution of built-in property names at top-level and within nested paths, including present and missing-value scenarios.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a09d09d and 9435920.

📒 Files selected for processing (1)
  • packages/core-base/src/resolver.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core-base/src/resolver.ts

📝 Walkthrough

Walkthrough

Added a guard in the resolver to use hasOwn before accessing object properties to avoid prototype-key collisions, and added tests covering top-level and nested key paths that match JavaScript built-in Object.prototype names. Public API signatures remain unchanged.

Changes

Cohort / File(s) Summary
Resolver Guard Check
packages/core-base/src/resolver.ts
Imported hasOwn and added a guard in resolveValue (use hasOwn(last as object, key) and return null when missing) to prevent accessing prototype properties when traversing key paths.
Test Coverage for Built-in Keys
packages/core-base/test/resolver.test.ts
Added tests for Object.prototype built-in key names covering present/missing top-level keys and nested paths (e.g., a.toString.c) to validate resolver behavior for built-in-named keys.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 I nibble keys both big and small,
When toString knocks I guard the wall,
hasOwn hops in to check the door,
No prototype tricks confuse me more,
Now nested paths behave for all.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: fixing how key paths containing JavaScript built-in property names are handled.
Linked Issues check ✅ Passed The PR implements guard checks using hasOwn to safely access properties and adds test coverage for builtin-named keys, directly addressing issue #1838 requirements for consistent handling.
Out of Scope Changes check ✅ Passed All changes are scoped to resolver.ts and resolver.test.ts, directly addressing the linked issue #1838 with no unrelated modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/1838

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@kazupon kazupon added the Type: Bug Bug or Bug fixes label Feb 25, 2026
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Feb 25, 2026

Deploying vue-i18n-next with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9435920
Status: ✅  Deploy successful!
Preview URL: https://d2b3c959.vue-i18n-next.pages.dev
Branch Preview URL: https://fix-1838.vue-i18n-next.pages.dev

View logs

@github-actions
Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
core.esm-browser.prod.js 44.09 kB (+0.01 kB) 12.69 kB (+0.01 kB) 11.37 kB (+0.04 kB)
core.global.prod.js 35.10 kB (+0.01 kB) 11.74 kB (+0.01 kB) 10.54 kB (-0.02 kB)
core.runtime.esm-browser.prod.js 26.80 kB (+0.01 kB) 8.31 kB (+0.01 kB) 7.45 kB (+0.01 kB)
core.runtime.global.prod.js 20.23 kB (+0.01 kB) 7.66 kB (+0.01 kB) 6.89 kB (+0.01 kB)
message-compiler.esm-browser.prod.js 23.42 kB 6.50 kB 5.83 kB
message-compiler.global.prod.js 20.66 kB 6.26 kB 5.62 kB
petite-vue-i18n-core.esm-browser.prod.js 23.09 kB 7.55 kB 6.78 kB
petite-vue-i18n-core.global.prod.js 17.56 kB 6.69 kB 6.04 kB
petite-vue-i18n.esm-browser.prod.js 42.92 kB 12.53 kB 11.23 kB
petite-vue-i18n.global.prod.js 33.95 kB 11.23 kB 10.13 kB
petite-vue-i18n.runtime.esm-browser.prod.js 25.48 kB 8.05 kB 7.27 kB
petite-vue-i18n.runtime.global.prod.js 19.08 kB 7.12 kB 6.45 kB
vue-i18n.esm-browser.prod.js 56.54 kB (+0.01 kB) 16.19 kB (+0.00 kB) 14.53 kB (+0.01 kB)
vue-i18n.global.prod.js 44.59 kB (+0.01 kB) 14.59 kB (+0.00 kB) 13.15 kB (+0.01 kB)
vue-i18n.runtime.esm-browser.prod.js 39.09 kB (+0.01 kB) 11.72 kB (+0.01 kB) 10.60 kB (+0.00 kB)
vue-i18n.runtime.global.prod.js 29.71 kB (+0.01 kB) 10.53 kB (+0.00 kB) 9.52 kB (+0.01 kB)

Usages

Name Size Gzip Brotli
packages/size-check-core (@intlify/core) 12.00 kB 4.77 kB 4.29 kB
packages/size-check-petite-vue-i18n (petite-vue-i18n) 84.10 kB 32.21 kB 29.04 kB
packages/size-check-vue-i18n (vue-i18n) 88.79 kB 33.52 kB 30.19 kB

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 25, 2026

Open in StackBlitz

@intlify/core

npm i https://pkg.pr.new/@intlify/core@2403

@intlify/core-base

npm i https://pkg.pr.new/@intlify/core-base@2403

@intlify/devtools-types

npm i https://pkg.pr.new/@intlify/devtools-types@2403

@intlify/message-compiler

npm i https://pkg.pr.new/@intlify/message-compiler@2403

petite-vue-i18n

npm i https://pkg.pr.new/petite-vue-i18n@2403

@intlify/shared

npm i https://pkg.pr.new/@intlify/shared@2403

vue-i18n

npm i https://pkg.pr.new/vue-i18n@2403

@intlify/vue-i18n-core

npm i https://pkg.pr.new/@intlify/vue-i18n-core@2403

commit: 9435920

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/core-base/src/resolver.ts (1)

299-301: ⚠️ Potential issue | 🟠 Major

resolveWithKeyValue still exposes the same prototype-collision bug this PR fixes in resolveValue.

obj[path] is accessed without an hasOwn guard, so a path like toString or hasOwnProperty on an empty object returns the prototype method rather than null. This makes the two exported resolvers inconsistent in their prototype-safety guarantees.

🛡️ Proposed fix
 export function resolveWithKeyValue(obj: unknown, path: Path): PathValue {
-  return isObject(obj) ? obj[path] : null
+  return isObject(obj) && hasOwn(obj as object, path) ? obj[path] : null
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core-base/src/resolver.ts` around lines 299 - 301,
resolveWithKeyValue exposes a prototype-collision bug because it reads obj[path]
without checking ownership; update resolveWithKeyValue to mirror resolveValue's
prototype-safety by first verifying the key is an own property (e.g., use
Object.prototype.hasOwnProperty.call(obj, path) or the existing hasOwn util) and
only then return obj[path], otherwise return null so that special keys like
"toString" or "hasOwnProperty" on plain objects do not return prototype methods.
🧹 Nitpick comments (1)
packages/core-base/test/resolver.test.ts (1)

136-167: Good coverage — note the correctness of __proto__ fixture depends on computed-property notation.

{ [k]: 'hi' } (computed) correctly creates an own property named __proto__, unlike { __proto__: 'hi' } (shorthand literal) which sets the prototype. The tests are correct as written, but this distinction is fragile: if a future maintainer copies the fixture and switches to shorthand notation, the __proto__ cases would silently change behavior. A brief comment would prevent that.

📝 Suggested comment
     const builtins = [
       'constructor',
       'hasOwnProperty',
       'isPrototypeOf',
       'propertyIsEnumerable',
       'toLocaleString',
       'toString',
       'valueOf',
-      '__proto__'
+      '__proto__' // must stay as computed property [k] in fixtures, not shorthand literal
     ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core-base/test/resolver.test.ts` around lines 136 - 167, Add a brief
explanatory comment in the test 'Object.prototype built-in key paths (issue
`#1838`)' next to the builtins array or each fixture to warn that the __proto__
case relies on computed-property notation ({ [k]: 'hi' }) to create an own
property; explicitly state that using shorthand literal ({ __proto__: 'hi' })
would mutate the prototype and change behavior of resolveValue, so maintainers
must keep the computed form when testing resolveValue with '__proto__'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/core-base/src/resolver.ts`:
- Around line 299-301: resolveWithKeyValue exposes a prototype-collision bug
because it reads obj[path] without checking ownership; update
resolveWithKeyValue to mirror resolveValue's prototype-safety by first verifying
the key is an own property (e.g., use Object.prototype.hasOwnProperty.call(obj,
path) or the existing hasOwn util) and only then return obj[path], otherwise
return null so that special keys like "toString" or "hasOwnProperty" on plain
objects do not return prototype methods.

---

Nitpick comments:
In `@packages/core-base/test/resolver.test.ts`:
- Around line 136-167: Add a brief explanatory comment in the test
'Object.prototype built-in key paths (issue `#1838`)' next to the builtins array
or each fixture to warn that the __proto__ case relies on computed-property
notation ({ [k]: 'hi' }) to create an own property; explicitly state that using
shorthand literal ({ __proto__: 'hi' }) would mutate the prototype and change
behavior of resolveValue, so maintainers must keep the computed form when
testing resolveValue with '__proto__'.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 638f0a5 and a09d09d.

📒 Files selected for processing (2)
  • packages/core-base/src/resolver.ts
  • packages/core-base/test/resolver.test.ts

@kazupon kazupon merged commit 8039e71 into master Feb 25, 2026
36 checks passed
@kazupon kazupon deleted the fix/1838 branch February 25, 2026 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Key paths containing javascript built-ins are handled inconsistently

1 participant