CVE-2024-52810
Description
@intlify/shared is a shared library for the intlify project. The latest version of @intlify/shared (10.0.4) is vulnerable to Prototype Pollution through the entry function(s) lib.deepCopy. An attacker can supply a payload with Object.prototype setter to introduce or modify properties within the global prototype chain, causing denial of service (DoS) as the minimum consequence. Moreover, the consequences of this vulnerability can escalate to other injection-based attacks, depending on how the library integrates within the application. For instance, if the polluted property propagates to sensitive Node.js APIs (e.g., exec, eval), it could enable an attacker to execute arbitrary commands within the application's context. This issue has been addressed in versions 9.14.2, and 10.0.5. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@intlify/sharednpm | >= 9.7.0, < 9.14.2 | 9.14.2 |
@intlify/vue-i18n-corenpm | >= 9.7.0, < 9.14.2 | 9.14.2 |
vue-i18nnpm | >= 9.7.0, < 9.14.2 | 9.14.2 |
petite-vue-i18nnpm | >= 10.0.0, < 10.0.5 | 10.0.5 |
@intlify/sharednpm | >= 10.0.0, < 10.0.5 | 10.0.5 |
@intlify/vue-i18n-corenpm | >= 10.0.0, < 10.0.5 | 10.0.5 |
vue-i18nnpm | >= 10.0.0, < 10.0.5 | 10.0.5 |
Patches
35448139375d1be77fccb0fe29f20909ef8c9Merge commit from fork
20 files changed · +210 −159
packages/core-base/src/compilation.ts+3 −2 modified@@ -4,6 +4,7 @@ import { detectHtmlTag } from '@intlify/message-compiler' import { + create, format, hasOwn, isBoolean, @@ -32,10 +33,10 @@ function checkHtmlMessage(source: string, warnHtmlMessage?: boolean): void { } const defaultOnCacheKey = (message: string): string => message -let compileCache: unknown = Object.create(null) +let compileCache: unknown = create() export function clearCompileCache(): void { - compileCache = Object.create(null) + compileCache = create() } export function isMessageAST(val: unknown): val is ResourceNode {
packages/core-base/src/context.ts+11 −8 modified@@ -2,6 +2,7 @@ import { assign, + create, isArray, isBoolean, isFunction, @@ -507,23 +508,23 @@ export function createCoreContext<Message = string>(options: any = {}): any { : _locale const messages = isPlainObject(options.messages) ? options.messages - : { [_locale]: {} } + : createResources(_locale) const datetimeFormats = !__LITE__ ? isPlainObject(options.datetimeFormats) ? options.datetimeFormats - : { [_locale]: {} } - : { [_locale]: {} } + : createResources(_locale) + : createResources(_locale) const numberFormats = !__LITE__ ? isPlainObject(options.numberFormats) ? options.numberFormats - : { [_locale]: {} } - : { [_locale]: {} } + : createResources(_locale) + : createResources(_locale) const modifiers = assign( - {}, - options.modifiers || {}, + create(), + options.modifiers, getDefaultLinkedModifiers<Message>() ) - const pluralRules = options.pluralRules || {} + const pluralRules = options.pluralRules || create() const missing = isFunction(options.missing) ? options.missing : null const missingWarn = isBoolean(options.missingWarn) || isRegExp(options.missingWarn) @@ -628,6 +629,8 @@ export function createCoreContext<Message = string>(options: any = {}): any { return context } +const createResources = (locale: Locale) => ({ [locale]: create() }) + /** @internal */ export function isTranslateFallbackWarn( fallback: boolean | RegExp,
packages/core-base/src/datetime.ts+3 −2 modified@@ -1,5 +1,6 @@ import { assign, + create, isBoolean, isDate, isEmptyObject, @@ -322,8 +323,8 @@ export function parseDateTimeArgs( ...args: unknown[] ): [string, number | Date, DateTimeOptions, Intl.DateTimeFormatOptions] { const [arg1, arg2, arg3, arg4] = args - const options = {} as DateTimeOptions - let overrides = {} as Intl.DateTimeFormatOptions + const options = create() as DateTimeOptions + let overrides = create() as Intl.DateTimeFormatOptions let value: number | Date if (isString(arg1)) {
packages/core-base/src/number.ts+15 −14 modified@@ -1,31 +1,32 @@ import { - isString, + assign, + create, isBoolean, - isPlainObject, - isNumber, isEmptyObject, - assign + isNumber, + isPlainObject, + isString } from '@intlify/shared' import { handleMissing, isTranslateFallbackWarn, - NOT_REOSLVED, - MISSING_RESOLVE_VALUE + MISSING_RESOLVE_VALUE, + NOT_REOSLVED } from './context' -import { CoreWarnCodes, getWarnMessage } from './warnings' import { CoreErrorCodes, createCoreError } from './errors' -import { Availabilities } from './intl' import { getLocale } from './fallbacker' +import { Availabilities } from './intl' +import { CoreWarnCodes, getWarnMessage } from './warnings' -import type { Locale, FallbackLocale } from './runtime' +import type { CoreContext, CoreInternalContext } from './context' +import type { LocaleOptions } from './fallbacker' +import type { FallbackLocale, Locale } from './runtime' import type { NumberFormat, - NumberFormats as NumberFormatsType, NumberFormatOptions, + NumberFormats as NumberFormatsType, PickupFormatKeys } from './types' -import type { LocaleOptions } from './fallbacker' -import type { CoreContext, CoreInternalContext } from './context' /** * # number @@ -317,8 +318,8 @@ export function parseNumberArgs( ...args: unknown[] ): [string, number, NumberOptions, Intl.NumberFormatOptions] { const [arg1, arg2, arg3, arg4] = args - const options = {} as NumberOptions - let overrides = {} as Intl.NumberFormatOptions + const options = create() as NumberOptions + let overrides = create() as Intl.NumberFormatOptions if (!isNumber(arg1)) { throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT)
packages/core-base/src/runtime.ts+3 −2 modified@@ -1,6 +1,7 @@ import { HelperNameMap } from '@intlify/message-compiler' import { assign, + create, isArray, isFunction, isNumber, @@ -360,7 +361,7 @@ export function createMessageContext<T = string, N = {}>( const list = (index: number): unknown => _list[index] // eslint-disable-next-line @typescript-eslint/no-explicit-any - const _named = options.named || ({} as any) + const _named = options.named || (create() as any) isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named) const named = (key: string): unknown => _named[key] @@ -437,7 +438,7 @@ export function createMessageContext<T = string, N = {}>( [HelperNameMap.TYPE]: type, [HelperNameMap.INTERPOLATE]: interpolate, [HelperNameMap.NORMALIZE]: normalize, - [HelperNameMap.VALUES]: assign({}, _list, _named) + [HelperNameMap.VALUES]: assign(create(), _list, _named) } return ctx
packages/core-base/src/translate.ts+5 −4 modified@@ -1,5 +1,6 @@ import { assign, + create, escapeHtml, generateCodeFrame, generateFormatCacheKey, @@ -677,7 +678,7 @@ export function translate< : [ key, locale, - (messages as unknown as LocaleMessages<Message>)[locale] || {} + (messages as unknown as LocaleMessages<Message>)[locale] || create() ] // NOTE: // Fix to work around `ssrTransfrom` bug in Vite. @@ -830,7 +831,7 @@ function resolveMessageFormat<Messages, Message>( } = context const locales = localeFallbacker(context as any, fallbackLocale, locale) // eslint-disable-line @typescript-eslint/no-explicit-any - let message: LocaleMessageValue<Message> = {} + let message: LocaleMessageValue<Message> = create() let targetLocale: Locale | undefined let format: PathValue = null let from: Locale = locale @@ -869,7 +870,7 @@ function resolveMessageFormat<Messages, Message>( } message = - (messages as unknown as LocaleMessages<Message>)[targetLocale] || {} + (messages as unknown as LocaleMessages<Message>)[targetLocale] || create() // for vue-devtools timeline event let start: number | null = null @@ -1044,7 +1045,7 @@ export function parseTranslateArgs<Message = string>( ...args: unknown[] ): [Path | MessageFunction<Message> | ResourceNode, TranslateOptions] { const [arg1, arg2, arg3] = args - const options = {} as TranslateOptions + const options = create() as TranslateOptions if ( !isString(arg1) &&
packages/message-compiler/src/tokenizer.ts+5 −4 modified@@ -1,10 +1,10 @@ -import { createScanner, CHAR_SP as SPACE, CHAR_LF as NEW_LINE } from './scanner' +import { CompileErrorCodes, createCompileError } from './errors' import { createLocation, createPosition } from './location' -import { createCompileError, CompileErrorCodes } from './errors' +import { createScanner, CHAR_LF as NEW_LINE, CHAR_SP as SPACE } from './scanner' -import type { Scanner } from './scanner' -import type { SourceLocation, Position } from './location' +import type { Position, SourceLocation } from './location' import type { TokenizeOptions } from './options' +import type { Scanner } from './scanner' export const enum TokenTypes { Text, // 0 @@ -447,6 +447,7 @@ export function createTokenizer( function readText(scnr: Scanner): string { let buf = '' + while (true) { const ch = scnr.currentChar() if (
packages/shared/src/messages.ts+5 −2 modified@@ -1,4 +1,4 @@ -import { isArray, isObject } from './utils' +import { create, isArray, isObject } from './utils' const isNotObjectOrIsArray = (val: unknown) => !isObject(val) || isArray(val) // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -14,10 +14,13 @@ export function deepCopy(src: any, des: any): void { // using `Object.keys` which skips prototype properties Object.keys(src).forEach(key => { + if (key === '__proto__') { + return + } // if src[key] is an object/array, set des[key] // to empty object/array to prevent setting by reference if (isObject(src[key]) && !isObject(des[key])) { - des[key] = Array.isArray(src[key]) ? [] : {} + des[key] = Array.isArray(src[key]) ? [] : create() } if (isNotObjectOrIsArray(des[key]) || isNotObjectOrIsArray(src[key])) {
packages/shared/src/utils.ts+4 −1 modified@@ -81,6 +81,9 @@ export const isEmptyObject = (val: unknown): val is boolean => export const assign = Object.assign +const _create = Object.create +export const create = (obj: object | null = null): object => _create(obj) + let _globalThis: any export const getGlobalThis = (): any => { // prettier-ignore @@ -95,7 +98,7 @@ export const getGlobalThis = (): any => { ? window : typeof global !== 'undefined' ? global - : {}) + : create()) ) }
packages/shared/test/messages.test.ts+31 −0 modified@@ -48,3 +48,34 @@ test('deepCopy merges without mutating src argument', () => { // should not mutate source object expect(msg1).toStrictEqual(copy1) }) + +describe('CVE-2024-52810', () => { + test('__proto__', () => { + const source = '{ "__proto__": { "pollutedKey": 123 } }' + const dest = {} + + deepCopy(JSON.parse(source), dest) + expect(dest).toEqual({}) + // @ts-ignore -- initialize polluted property + expect(JSON.parse(JSON.stringify({}.__proto__))).toEqual({}) + }) + + test('nest __proto__', () => { + const source = '{ "foo": { "__proto__": { "pollutedKey": 123 } } }' + const dest = {} + + deepCopy(JSON.parse(source), dest) + expect(dest).toEqual({ foo: {} }) + // @ts-ignore -- initialize polluted property + expect(JSON.parse(JSON.stringify({}.__proto__))).toEqual({}) + }) + + test('constructor prototype', () => { + const source = '{ "constructor": { "prototype": { "polluted": 1 } } }' + const dest = {} + + deepCopy(JSON.parse(source), dest) + // @ts-ignore -- initialize polluted property + expect({}.polluted).toBeUndefined() + }) +})
packages/vue-i18n-core/src/components/base.ts+1 −1 modified@@ -1,7 +1,7 @@ import { Composer } from '../composer' -import type { I18nScope } from '../i18n' import type { Locale } from '@intlify/core-base' +import type { I18nScope } from '../i18n' export type ComponentI18nScope = Exclude<I18nScope, 'local'>
packages/vue-i18n-core/src/components/DatetimeFormat.ts+5 −5 modified@@ -1,16 +1,16 @@ -import { defineComponent } from 'vue' -import { assign } from '@intlify/shared' import { DATETIME_FORMAT_OPTIONS_KEYS } from '@intlify/core-base' +import { assign } from '@intlify/shared' +import { defineComponent } from 'vue' import { useI18n } from '../i18n' import { DatetimePartsSymbol } from '../symbols' -import { renderFormatter } from './formatRenderer' import { baseFormatProps } from './base' +import { renderFormatter } from './formatRenderer' -import type { VNodeProps } from 'vue' import type { DateTimeOptions } from '@intlify/core-base' +import type { VNodeProps } from 'vue' import type { Composer, ComposerInternal } from '../composer' -import type { FormattableProps } from './formatRenderer' import type { BaseFormatProps } from './base' +import type { FormattableProps } from './formatRenderer' /** * DatetimeFormat Component Props
packages/vue-i18n-core/src/components/formatRenderer.ts+8 −8 modified@@ -1,15 +1,15 @@ +import { assign, create, isArray, isObject, isString } from '@intlify/shared' import { h } from 'vue' import { getFragmentableTag } from './utils' -import { isString, isObject, isArray, assign } from '@intlify/shared' +import type { DateTimeOptions, NumberOptions } from '@intlify/core-base' import type { RenderFunction, SetupContext, VNode, - VNodeChild, - VNodeArrayChildren + VNodeArrayChildren, + VNodeChild } from 'vue' -import type { NumberOptions, DateTimeOptions } from '@intlify/core-base' import type { BaseFormatProps } from './base' /** @@ -61,7 +61,7 @@ export function renderFormatter< return (): VNodeChild => { const options = { part: true } as Arg - let overrides = {} as FormatOverrideOptions + let overrides = create() as FormatOverrideOptions if (props.locale) { options.locale = props.locale @@ -78,9 +78,9 @@ export function renderFormatter< // Filter out number format options only overrides = Object.keys(props.format).reduce((options, prop) => { return slotKeys.includes(prop) - ? assign({}, options, { [prop]: (props.format as any)[prop] }) // eslint-disable-line @typescript-eslint/no-explicit-any + ? assign(create(), options, { [prop]: (props.format as any)[prop] }) // eslint-disable-line @typescript-eslint/no-explicit-any : options - }, {}) + }, create()) } const parts = partFormatter(...[props.value, options, overrides]) @@ -100,7 +100,7 @@ export function renderFormatter< children = [parts] } - const assignedAttrs = assign({}, attrs) + const assignedAttrs = assign(create(), attrs) const tag = isString(props.tag) || isObject(props.tag) ? props.tag
packages/vue-i18n-core/src/components/index.ts+4 −4 modified@@ -1,5 +1,5 @@ -export { ComponentI18nScope, BaseFormatProps } from './base' +export { BaseFormatProps, ComponentI18nScope } from './base' +export { DatetimeFormat, DatetimeFormatProps, I18nD } from './DatetimeFormat' export { FormattableProps } from './formatRenderer' -export { Translation, I18nT, TranslationProps } from './Translation' -export { NumberFormat, I18nN, NumberFormatProps } from './NumberFormat' -export { DatetimeFormat, I18nD, DatetimeFormatProps } from './DatetimeFormat' +export { I18nN, NumberFormat, NumberFormatProps } from './NumberFormat' +export { I18nT, Translation, TranslationProps } from './Translation'
packages/vue-i18n-core/src/components/NumberFormat.ts+5 −5 modified@@ -1,16 +1,16 @@ -import { defineComponent } from 'vue' -import { assign } from '@intlify/shared' import { NUMBER_FORMAT_OPTIONS_KEYS } from '@intlify/core-base' +import { assign } from '@intlify/shared' +import { defineComponent } from 'vue' import { useI18n } from '../i18n' import { NumberPartsSymbol } from '../symbols' -import { renderFormatter } from './formatRenderer' import { baseFormatProps } from './base' +import { renderFormatter } from './formatRenderer' -import type { VNodeProps } from 'vue' import type { NumberOptions } from '@intlify/core-base' +import type { VNodeProps } from 'vue' import type { Composer, ComposerInternal } from '../composer' -import type { FormattableProps } from './formatRenderer' import type { BaseFormatProps } from './base' +import type { FormattableProps } from './formatRenderer' /** * NumberFormat Component Props
packages/vue-i18n-core/src/components/Translation.ts+7 −7 modified@@ -1,12 +1,12 @@ -import { h, defineComponent } from 'vue' -import { isNumber, isString, isObject, assign } from '@intlify/shared' -import { TranslateVNodeSymbol } from '../symbols' +import { assign, create, isNumber, isObject, isString } from '@intlify/shared' +import { defineComponent, h } from 'vue' import { useI18n } from '../i18n' +import { TranslateVNodeSymbol } from '../symbols' import { baseFormatProps } from './base' -import { getInterpolateArg, getFragmentableTag } from './utils' +import { getFragmentableTag, getInterpolateArg } from './utils' -import type { VNodeChild, VNodeProps } from 'vue' import type { TranslateOptions } from '@intlify/core-base' +import type { VNodeChild, VNodeProps } from 'vue' import type { Composer, ComposerInternal } from '../composer' import type { BaseFormatProps } from './base' @@ -59,7 +59,7 @@ export const TranslationImpl = /*#__PURE__*/ defineComponent({ return (): VNodeChild => { const keys = Object.keys(slots).filter(key => key !== '_') - const options = {} as TranslateOptions + const options = create() as TranslateOptions if (props.locale) { options.locale = props.locale } @@ -73,7 +73,7 @@ export const TranslationImpl = /*#__PURE__*/ defineComponent({ arg, options ) - const assignedAttrs = assign({}, attrs) + const assignedAttrs = assign(create(), attrs) const tag = isString(props.tag) || isObject(props.tag) ? props.tag
packages/vue-i18n-core/src/components/utils.ts+2 −1 modified@@ -1,3 +1,4 @@ +import { create } from '@intlify/shared' import { Fragment } from 'vue' import type { NamedValue } from '@intlify/core-base' @@ -27,7 +28,7 @@ export function getInterpolateArg( arg[key] = slot() } return arg - }, {} as NamedValue) + }, create() as NamedValue) } }
packages/vue-i18n-core/src/index.ts+83 −83 modified@@ -1,120 +1,120 @@ -import { getGlobalThis } from '@intlify/shared' import { setDevToolsHook } from '@intlify/core-base' +import { getGlobalThis } from '@intlify/shared' import { initDev, initFeatureFlags } from './misc' export { - SchemaParams, - LocaleParams, - Path, - PathValue, - NamedValue, - Locale, + CompileError, + DateTimeOptions, FallbackLocale, - LocaleMessageValue, - LocaleMessageDictionary, - LocaleMessageType, - LocaleMessages, - LocaleMessage, - NumberFormat as IntlNumberFormat, DateTimeFormat as IntlDateTimeFormat, DateTimeFormats as IntlDateTimeFormats, - NumberFormats as IntlNumberFormats, - LocaleMatcher as IntlLocaleMatcher, FormatMatcher as IntlFormatMatcher, - MessageFunction, - MessageFunctions, - PluralizationRule, + LocaleMatcher as IntlLocaleMatcher, + NumberFormat as IntlNumberFormat, + NumberFormats as IntlNumberFormats, LinkedModifiers, - TranslateOptions, - DateTimeOptions, - NumberOptions, - PostTranslationHandler, - MessageResolver, + Locale, + LocaleMessage, + LocaleMessageDictionary, + LocaleMessages, + LocaleMessageType, + LocaleMessageValue, + LocaleParams, MessageCompiler, MessageCompilerContext, - CompileError, MessageContext, - RemovedIndexResources + MessageFunction, + MessageFunctions, + MessageResolver, + NamedValue, + NumberOptions, + Path, + PathValue, + PluralizationRule, + PostTranslationHandler, + RemovedIndexResources, + SchemaParams, + TranslateOptions } from '@intlify/core-base' export { - VueMessageType, - DefineLocaleMessage, - DefaultLocaleMessageSchema, - DefineDateTimeFormat, - DefaultDateTimeFormatSchema, - DefineNumberFormat, - DefaultNumberFormatSchema, - MissingHandler, - ComposerOptions, + BaseFormatProps, + ComponentI18nScope, + DatetimeFormat, + DatetimeFormatProps, + FormattableProps, + I18nD, + I18nN, + I18nT, + NumberFormat, + NumberFormatProps, + Translation, + TranslationProps +} from './components' +export { Composer, ComposerCustom, - CustomBlock, - CustomBlocks, - ComposerTranslation, ComposerDateTimeFormatting, ComposerNumberFormatting, - ComposerResolveLocaleMessageTranslation + ComposerOptions, + ComposerResolveLocaleMessageTranslation, + ComposerTranslation, + CustomBlock, + CustomBlocks, + DefaultDateTimeFormatSchema, + DefaultLocaleMessageSchema, + DefaultNumberFormatSchema, + DefineDateTimeFormat, + DefineLocaleMessage, + DefineNumberFormat, + MissingHandler, + VueMessageType } from './composer' export { - TranslateResult, + TranslationDirective, + vTDirective, + VTDirectiveValue +} from './directive' +export { + ComposerAdditionalOptions, + ComposerExtender, + createI18n, + ExportedGlobalComposer, + I18n, + I18nAdditionalOptions, + I18nInjectionKey, + I18nMode, + I18nOptions, + I18nScope, + useI18n, + UseI18nOptions +} from './i18n' +export { Choice, - LocaleMessageObject, - PluralizationRulesMap, - WarnHtmlInMessageLevel, DateTimeFormatResult, + LocaleMessageObject, NumberFormatResult, - VueI18nOptions, + PluralizationRulesMap, + TranslateResult, VueI18n, - VueI18nTranslation, - VueI18nTranslationChoice, VueI18nDateTimeFormatting, + VueI18nExtender, VueI18nNumberFormatting, + VueI18nOptions, VueI18nResolveLocaleMessageTranslation, - VueI18nExtender + VueI18nTranslation, + VueI18nTranslationChoice, + WarnHtmlInMessageLevel } from './legacy' -export { - createI18n, - useI18n, - I18nInjectionKey, - I18nOptions, - I18nAdditionalOptions, - I18n, - I18nMode, - I18nScope, - ComposerAdditionalOptions, - UseI18nOptions, - ExportedGlobalComposer, - ComposerExtender -} from './i18n' -export { - Translation, - I18nT, - NumberFormat, - I18nN, - DatetimeFormat, - I18nD, - TranslationProps, - NumberFormatProps, - DatetimeFormatProps, - FormattableProps, - BaseFormatProps, - ComponentI18nScope -} from './components' -export { - vTDirective, - VTDirectiveValue, - TranslationDirective -} from './directive' -export { I18nPluginOptions } from './plugin' export { VERSION } from './misc' +export { I18nPluginOptions } from './plugin' export { Disposer } from './types' export type { - IsNever, IsEmptyObject, - PickupPaths, + IsNever, + PickupFormatPathKeys, PickupKeys, - PickupFormatPathKeys + PickupPaths } from '@intlify/core-base' if (__ESM_BUNDLER__ && !__TEST__) {
packages/vue-i18n-core/src/utils.ts+9 −5 modified@@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { + create, deepCopy, hasOwn, isArray, @@ -69,7 +70,7 @@ export function handleFlatJson(obj: unknown): unknown { let hasStringValue = false for (let i = 0; i < lastIndex; i++) { if (!(subKeys[i] in currentObj)) { - currentObj[subKeys[i]] = {} + currentObj[subKeys[i]] = create() } if (!isObject(currentObj[subKeys[i]])) { __DEV__ && @@ -108,16 +109,16 @@ export function getLocaleMessages<Messages = {}>( const ret = (isPlainObject(messages) ? messages : isArray(__i18n) - ? {} - : { [locale]: {} }) as Record<string, any> + ? create() + : { [locale]: create() }) as Record<string, any> // merge locale messages of i18n custom block if (isArray(__i18n)) { __i18n.forEach(custom => { if ('locale' in custom && 'resource' in custom) { const { locale, resource } = custom if (locale) { - ret[locale] = ret[locale] || {} + ret[locale] = ret[locale] || create() deepCopy(resource, ret[locale]) } else { deepCopy(resource, ret) @@ -149,7 +150,10 @@ export function adjustI18nResources( options: ComposerOptions, componentOptions: any ): void { - let messages = isObject(options.messages) ? options.messages : {} + // prettier-ignore + let messages = isObject(options.messages) + ? options.messages + : create() as NonNullable<ComposerOptions['messages']> if ('__i18nGlobal' in componentOptions) { messages = getLocaleMessages(gl.locale.value as Locale, { messages,
packages/vue-i18n-core/src/warnings.ts+1 −1 modified@@ -1,5 +1,5 @@ -import { format } from '@intlify/shared' import { CORE_WARN_CODES_EXTEND_POINT } from '@intlify/core-base' +import { format } from '@intlify/shared' export const I18nWarnCodes = { FALLBACK_TO_ROOT: CORE_WARN_CODES_EXTEND_POINT, // 8
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.