Back to Blog
high SEVERITY6 min read

How Prototype Pollution Happens in Vue I18n's handleFlatJson and How to Fix It

CVE-2025-27597 is a prototype pollution vulnerability in @intlify/core-base's `handleFlatJson` function that could allow attackers to pollute the JavaScript prototype chain through maliciously crafted internationalization data. The fix upgrades @intlify/core-base from version 9.1.9 to 11.1.10, which implements stricter input handling to prevent untrusted data from modifying object prototypes.

O
By Orbis AppSec
Published August 15, 2026Reviewed August 15, 2026

Answer Summary

CVE-2025-27597 is a prototype pollution vulnerability in Vue I18n's @intlify/core-base library (versions prior to 9.1.11), specifically in the `handleFlatJson` function. The vulnerability allows attackers to inject malicious keys like `__proto__`, `constructor`, or `prototype` into the object prototype chain through crafted i18n message data. The fix upgrades @intlify/core-base to version 11.1.10, which implements proper input validation and sanitization to reject dangerous property names before they can pollute the prototype.

Vulnerability at a Glance

cweCWE-1321 (Improperly Controlled Modification of Object Prototype Attributes in JavaScript)
fixUpgrade @intlify/core-base from 9.1.9 to 11.1.10 with enhanced input validation
riskRemote code execution, denial of service, authentication bypass through prototype chain manipulation
languageJavaScript/TypeScript (Vue.js ecosystem)
root causeUnsafe assignment of user-controlled keys to objects without validating for prototype-polluting properties
vulnerabilityPrototype Pollution in handleFlatJson

How Prototype Pollution Happens in Vue I18n's handleFlatJson and How to Fix It

Introduction

In the unibestX project, Trivy security scanning detected a high-severity prototype pollution vulnerability (CVE-2025-27597) lurking in the dependency tree within pnpm-lock.yaml. The vulnerability exists in @intlify/core-base version 9.1.9, specifically in the handleFlatJson function—a critical component that processes internationalization (i18n) message data.

This matters because Vue I18n applications worldwide handle user-influenced translation data, and if that data contains maliciously crafted keys, it could allow attackers to inject properties into JavaScript's prototype chain. For developers building multilingual applications, this represents a silent threat that bypasses traditional input validation because it operates at the prototype level, affecting every object in the application.

The Vulnerability Explained

What is Prototype Pollution?

Prototype pollution is a JavaScript-specific vulnerability where an attacker modifies the prototype of built-in objects (like Object.prototype) by injecting special property names. In JavaScript, when you access a property on an object, the engine searches up the prototype chain. If an attacker pollutes Object.prototype.__proto__ or Object.prototype.constructor, they can:

  • Override application logic
  • Bypass security checks
  • Inject malicious code into unexpected locations
  • Cause denial of service

The Vulnerable Code Pattern

The handleFlatJson function in @intlify/core-base 9.1.9 processes flat JSON structures used for i18n messages. Here's the problematic pattern:

// Vulnerable pattern in @intlify/core-base 9.1.9
// When processing i18n message data like:
const messageData = {
  "greeting": "Hello",
  "__proto__": { "isAdmin": true },  // Malicious key!
  "farewell": "Goodbye"
};

// The handleFlatJson function would iterate through keys and assign them:
for (const key in messageData) {
  targetObject[key] = messageData[key];  // VULNERABLE: No validation!
}

The vulnerability occurs because handleFlatJson accepts user-controlled keys from i18n message data without validating whether they're dangerous prototype-polluting properties.

Attack Scenario

Imagine an attacker crafts a malicious i18n translation file:

{
  "messages": {
    "welcome": "Welcome to our app",
    "__proto__": {
      "isAuthenticated": true,
      "isAdmin": true,
      "permissions": ["delete", "write"]
    }
  }
}

When the Vue I18n application loads this translation data through handleFlatJson, the __proto__ key gets processed, and suddenly:

// After prototype pollution:
const user = {};
console.log(user.isAdmin);           // true (polluted!)
console.log(user.isAuthenticated);   // true (polluted!)
console.log(user.permissions);       // ["delete", "write"] (polluted!)

An attacker could bypass authentication checks, escalate privileges, or manipulate application state across the entire application without modifying a single legitimate property.

Real-World Impact

For applications using @intlify/core-base 9.1.9:

  • Remote Translation Services: If i18n messages come from a CDN or API, an attacker could compromise that source
  • User-Generated Content: If users can upload or provide translation files, malicious actors could inject prototype pollution
  • Supply Chain Risk: Third-party translation management tools could be compromised, distributing polluted message files

The Fix

The fix upgrades @intlify/core-base from version 9.1.9 to 11.1.10, which implements proper input validation in the handleFlatJson function.

Changes Made

Looking at the PR diff, two critical files were updated:

1. package.json

- "vue": "^3.5.13"
+ "vue": "^3.5.13",
+ "@intlify/core-base": "11.1.10"

The explicit dependency pinning ensures the patched version is used.

2. pnpm-lock.yaml

- '@intlify/core-base@9.1.9':
-   resolution: {integrity: sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==}
-   engines: {node: '>= 10'}

+ '@intlify/core-base@11.1.10':
+   resolution: {integrity: sha512-JhRb40hD93Vk0BgMgDc/xMIFtdXPHoytzeK6VafBNOj6bb6oUZrGamXkBKecMsmGvDQQaPRGG2zpa25VCw8pyw==}
+   engines: {node: '>= 16'}

Notice the engine requirement increased from Node 10+ to Node 16+, indicating substantial internal changes for security.

How Version 11.1.10 Fixes the Issue

The patched version implements a property name allowlist approach:

// Fixed pattern in @intlify/core-base 11.1.10 (conceptual)
const DANGEROUS_KEYS = ['__proto__', 'constructor', 'prototype'];

function handleFlatJson(messageData, targetObject) {
  for (const key in messageData) {
    // VALIDATION: Check if key is dangerous
    if (DANGEROUS_KEYS.includes(key)) {
      console.warn(`Skipping dangerous key: ${key}`);
      continue;  // Skip prototype-polluting keys
    }

    // SAFE: Only assign validated keys
    targetObject[key] = messageData[key];
  }
}

The fix ensures that:
- ✅ Legitimate i18n keys like greeting, farewell, welcome still work
- ✅ Dangerous keys like __proto__, constructor, prototype are rejected
- ✅ The prototype chain remains unpolluted
- ✅ No valid translations are lost

Prevention & Best Practices

For Your Own Code

  1. Never Trust User-Controlled Keys: When building object assignment operations, always validate property names:
    ```javascript
    // BAD: Direct assignment without validation
    const config = {};
    Object.assign(config, userInput);

// GOOD: Validate keys first
const SAFE_KEYS = ['theme', 'language', 'notifications'];
const config = {};
for (const key of Object.keys(userInput)) {
if (SAFE_KEYS.includes(key)) {
config[key] = userInput[key];
}
}
```

  1. Use Object.create(null): When possible, create objects without a prototype:
    javascript // More resistant to prototype pollution const safeObject = Object.create(null);

  2. Freeze Prototypes: In security-critical code, freeze prototypes:
    javascript Object.freeze(Object.prototype); Object.freeze(Array.prototype);

  3. Keep Dependencies Updated: Prototype pollution vulnerabilities are discovered regularly. Use tools like npm audit and pnpm audit:
    bash pnpm audit pnpm update

  4. Use Static Analysis: Enable Trivy, Semgrep, or similar tools in your CI/CD pipeline to catch prototype pollution patterns before deployment.

Security Standards

  • CWE-1321: Improperly Controlled Modification of Object Prototype Attributes in JavaScript
  • OWASP: Prototype Pollution in the OWASP Attack Database

Key Takeaways

  • Prototype pollution in handleFlatJson could inject properties into Object.prototype through malicious i18n message keys like __proto__, silently affecting every object in the application.

  • The @intlify/core-base 9.1.9 vulnerability specifically affects applications that load i18n messages from untrusted sources (APIs, user uploads, third-party CDNs).

  • Upgrading to @intlify/core-base 11.1.10 adds validation that rejects dangerous property names before they reach object assignment, preventing prototype pollution while preserving legitimate translations.

  • Always validate property names when assigning user-controlled data to objects—don't rely on input validation alone; specifically reject __proto__, constructor, and prototype.

  • Prototype pollution is invisible to traditional security testing because it operates at the prototype level; automated tools like Trivy are essential for catching these vulnerabilities.

How Orbis AppSec Detected This

Source: I18n message data loaded from external sources or user-provided translation files in the @intlify/core-base handleFlatJson function

Sink: Unsafe property assignment operations in handleFlatJson that don't validate property names before adding them to the target object

Missing control: No validation to reject prototype-polluting keys (__proto__, constructor, prototype) before object assignment

CWE: CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes in JavaScript)

Fix: Upgrade @intlify/core-base from 9.1.9 to 11.1.10, which implements property name validation in handleFlatJson to reject dangerous keys before they can pollute the prototype chain.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

Prototype pollution in Vue I18n's handleFlatJson represents a subtle but dangerous vulnerability that could compromise applications handling multilingual content from untrusted sources. By upgrading @intlify/core-base to version 11.1.10, you're not just closing a security hole—you're ensuring that your application's prototype chain remains protected against a class of attacks that traditional input validation often misses.

The lesson here extends beyond this specific vulnerability: in JavaScript, always validate property names when processing user-controlled data, especially when that data will be assigned to objects. Prototype pollution is a reminder that security must operate at multiple levels—and that keeping dependencies up-to-date is a critical part of your defense strategy.

Make the upgrade today, and ensure your i18n pipeline remains secure.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3

Related Articles

high

How Denial of Service via Infinite Loop Happens in JavaScript Dependencies and How to Fix It

CVE-2026-67213 is a high-severity denial of service vulnerability in nanoid before version 5.1.6 that triggers an infinite loop during random ID generation when processing specially crafted input. We upgraded nanoid across the entire dependency tree to patch this flaw and prevent attackers from freezing application threads. This fix ensures that ID generation remains resilient even when handling adversarial input patterns.

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.

critical

How Remote Code Execution Happens in Handlebars Template Compilation and How to Fix It

CVE-2026-33937 is a critical remote code execution vulnerability in Handlebars.js that allows attackers to execute arbitrary code by passing maliciously crafted Abstract Syntax Tree (AST) objects to the compile() function. The vulnerability was patched in version 4.7.9, and we've upgraded to protect against this threat vector.