Visitar URL original
[bugfix] Fix locale('__proto__') corrupting the global locale by afonsojanu · Pull Request #6442 · moment/moment · GitHub
Skip to content

[bugfix] Fix locale('__proto__') corrupting the global locale - #6442

Merged
mattjohnsonpint merged 2 commits into
moment:developfrom
afonsojanu:fix/locale-proto-corruption
Sep 14, 2026
Merged

mattjohnsonpint merged 2 commits into
moment:developfrom
afonsojanu:fix/locale-proto-corruption

Conversation

@afonsojanu

Copy link
Copy Markdown
Contributor

Reported in #6440. loadLocale() checks whether a name is already loaded with locales[name] !== undefined, and since locales is a plain object, that lookup falls through to Object.prototype for names like __proto__, constructor, or prototype. The result then gets assigned as the global locale by getSetGlobalLocale, and every later call to format/calendar/fromNow throws because Object.prototype obviously isn't a real Locale.

Repro against current develop:

const moment = require('moment');
moment.locale('__proto__');
moment().format('LLLL'); // TypeError: locale.longDateFormat is not a function

The fix swaps both lookups in loadLocale to use the existing hasOwnProp helper (already used elsewhere in this file) instead of a plain property check, so an own-property-only lookup treats these names the same as any other locale that was never registered: not found, warn, keep the current locale.

Added a regression test in src/test/moment/locale.js covering __proto__, constructor, prototype, and toString. Ran pnpm validate (lint + full suite, 3930 tests / 164926 assertions) clean.

The internal locale registry is a plain object, so loadLocale()
checked whether a locale was already loaded with locales[name] !== undefined.
For names like __proto__, constructor, or prototype, that lookup walks
the prototype chain and returns an inherited value instead of a real
locale entry, which then gets stored as the global locale and breaks
every later formatting call until a valid locale is set again.

Switch both lookups in loadLocale to hasOwnProp so an unrecognized
name is always treated as not found, the same way it would be for any
other unknown locale string.
@afonsojanu
afonsojanu requested a review from a team as a code owner September 6, 2026 11:46
@mattjohnsonpint mattjohnsonpint changed the title Fix locale('__proto__') corrupting the global locale [bugfix] Fix locale('__proto__') corrupting the global locale Sep 11, 2026
@mattjohnsonpint

Copy link
Copy Markdown
Contributor

Thanks for the contribution and for identifying this bug. I added a small follow-up to guard the final locale registry lookup as well. Without that guard, browser builds could still resolve inherited properties such as constructor because they do not enter the CommonJS dynamic-loading path.

I also expanded the tests to cover the standard Object.prototype property names and added coverage for the fallback path when dynamic loading is skipped. This preserves the current locale and prevents subsequent formatting calls from failing in both CommonJS and browser environments.

@mattjohnsonpint
mattjohnsonpint merged commit 0d10504 into moment:develop Sep 14, 2026
26 checks passed
@mattjohnsonpint mattjohnsonpint added this to the 2.31.0 milestone Sep 14, 2026
@mattjohnsonpint mattjohnsonpint linked an issue Sep 14, 2026 that may be closed by this pull request
4 tasks done
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.

[Bug] moment.locale('__proto__') corrupts the global locale and breaks formatting

2 participants