npm-i18n-node-CVE-2026-41690-proto-pollution--kimi-k2.7-code--EiAKDZf

CVE-2026-41690 · kimi-k2.7-code

passgate full· reward 0.92
turns
60
tokens in
2.0M
tokens out
30k
exit
Submitted

Instruction

The Node.js package at /app contains a security vulnerability in the CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes) class.

Audit the codebase for a vulnerability of this class. If you find one, modify the project to remove it while keeping existing functionality intact. If you find no such vulnerability, make no changes.

The verifier runs behavioral end-to-end tests against the public API of the package.

Reward signals

r_apply1.00
r_test_pass1.00
r_pass_to_pass1.00
r_locality0.33
r_minimality1.00

Verifier · 0/0 security · 1/1 pass-to-pass

Candidate patch

i18n.js
index 178d9d6..e2917a5 100644@@ -1,3 +1,29 @@+/**+ * Prototype-pollution safe helpers.+ *+ * Locale trees are stored as objects without a prototype. This prevents keys+ * such as `__proto__`, `constructor` or `prototype` from being interpreted as+ * prototype accessors when reading locale files or manipulating nested+ * translations through object notation.+ */+const safeObject = () => Object.create(null)++const deepSafeObject = (value) => {+  if (Array.isArray(value)) {+    return value.map(deepSafeObject)+  }+  if (value !== null && typeof value === 'object') {+    const result = safeObject()+    for (const key in value) {+      if (Object.prototype.hasOwnProperty.call(value, key)) {+        result[key] = deepSafeObject(value[key])+      }+    }+    return result+  }+  return value+}+ /**  * @author      Created by Marcus Spiegel <spiegel@uscreen.de> on 2011-03-25.  * @link        https://github.com/mashpie/i18n-node@@ -40,6 +66,9 @@ const mergeLocaleTree = (target, source) => {     return target   }   for (const key in source) {+    if (!Object.prototype.hasOwnProperty.call(source, key)) {+      continue+    }     const value = source[key]     if (       value !== null &&@@ -47,7 +76,7 @@ const mergeLocaleTree = (target, source) => {       !Array.isArray(value)     ) {       if (target[key] === null || typeof target[key] !== 'object') {-        target[key] = {}+        target[key] = safeObject()       }       mergeLocaleTree(target[key], value)     } else {@@ -61,9 +90,9 @@ const mergeLocaleTree = (target, source) => {  * create constructor function  */ const i18n = function I18n(_OPTS = false) {-  const MessageformatInstanceForLocale = {}-  const PluralsForLocale = {}-  let locales = {}+  const MessageformatInstanceForLocale = safeObject()+  const PluralsForLocale = safeObject()+  let locales = safeObject()   const api = {     __: '__',     __n: '__n',@@ -249,7 +278,12 @@ const i18n = function I18n(_OPTS = false) {     // implicitly read all locales     if (Array.isArray(opt.locales)) {       if (opt.staticCatalog) {-        locales = opt.staticCatalog+        locales = safeObject()+        for (const staticLocale in opt.staticCatalog) {+          if (Object.prototype.hasOwnProperty.call(opt.staticCatalog, staticLocale)) {+            locales[staticLocale] = deepSafeObject(opt.staticCatalog[staticLocale])+          }+        }       } else {         opt.locales.forEach(read)       }@@ -367,7 +401,7 @@ const i18n = function I18n(_OPTS = false) {     } else {       mf = new Messageformat(targetLocale) -      mf.compiledFunctions = {}+      mf.compiledFunctions = safeObject()       MessageformatInstanceForLocale[targetLocale] = mf     } @@ -1213,7 +1247,7 @@ const i18n = function I18n(_OPTS = false) {               object = fixObject()             }             // If we are allowed to, create a new object along the path.-            object[index] = {}+            object[index] = safeObject()           } else {             // If we aren't allowed, remember that we need to re-traverse later on and...             reTraverse = true@@ -1228,7 +1262,7 @@ const i18n = function I18n(_OPTS = false) {         }         // Generate a fixer for the current level.         fixObject = () => {-          object[index] = {}+          object[index] = safeObject()           return object[index]         } @@ -1273,7 +1307,7 @@ const i18n = function I18n(_OPTS = false) {         // re-reads. mergeLocaleTree walks the parsed tree with for...in.         const parsed = parser.parse(localeFile)         if (!locales[locale] || typeof locales[locale] !== 'object') {-          locales[locale] = {}+          locales[locale] = safeObject()         }         mergeLocaleTree(locales[locale], parsed)       } catch (parseError) {@@ -1327,7 +1361,7 @@ const i18n = function I18n(_OPTS = false) {      // first time init has an empty file     if (!locales[locale]) {-      locales[locale] = {}+      locales[locale] = safeObject()     }      // writing to tmp and rename on success 

Trajectory