Skip to content

fix: allow a single rename to a target named after an Object.prototype member - #3127

Open
spokodev wants to merge 1 commit into
hapijs:masterfrom
spokodev:fix/rename-prototype-target
Open

fix: allow a single rename to a target named after an Object.prototype member#3127
spokodev wants to merge 1 commit into
hapijs:masterfrom
spokodev:fix/rename-prototype-target

Conversation

@spokodev

Copy link
Copy Markdown

internals.rename (lib/types/keys.js) tracks used rename targets in a plain {}, so the guard renamed[to] inherits from Object.prototype. When the target name collides with a prototype member (toString, constructor, __proto__, hasOwnProperty, valueOf, ...), renamed['toString'] is already truthy on the first rename, so even a single legitimate rename to such a name falsely raises object.rename.multiple.

This is self-inconsistent:

Joi.object().rename('a', 'toString', { multiple: true }).validate({ a: 1 });  // ok
Joi.object().rename('a', 'b').validate({ a: 1 });                             // ok
Joi.object().rename('a', 'toString').validate({ a: 1 });                      // throws object.rename.multiple

multiple defaults to false, so a single rename must succeed regardless of the target's name. The failure depends only on a name collision with a built-in prototype member.

Fix

Build the tracking map with Object.create(null) so membership reflects only actual renames, not inherited prototype keys.

Tests

Added a test for a single rename to a prototype-named target. It fails before the fix (object.rename.multiple) and passes after. Full suite is green with no leaks. Genuine duplicate-rename detection (two renames to the same target, including toString) and override detection are unchanged.

…e member

internals.rename tracked used rename targets in a plain {}, so the guard
renamed[to] inherited from Object.prototype. For a target colliding with a
prototype member (toString, constructor, __proto__, hasOwnProperty, ...),
renamed['toString'] was truthy on the first rename, so a single legitimate
rename to such a name falsely raised object.rename.multiple.

Use an Object.create(null) map so membership reflects only actual renames.
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.

1 participant