{"description":"Trending threats, MITRE ATT\u0026CK coverage, and detection metadata. Fed continuously.","favicon":"https://feed.craftedsignal.io/favicon-32x32.png","feed_url":"https://feed.craftedsignal.io/vendors/ardatan/feed.json","home_page_url":"https://feed.craftedsignal.io/","icon":"https://feed.craftedsignal.io/apple-touch-icon.png","items":[{"_cs_actors":[],"_cs_cpes":[],"_cs_cves":[],"_cs_exploited":false,"_cs_has_poc":false,"_cs_poc_references":[],"_cs_products":["@graphql-tools/utils (\u003e= 10.10.1, \u003c= 12.0.1)"],"_cs_severities":["high"],"_cs_tags":["prototype-pollution","supply-chain","graphql"],"_cs_type":"advisory","_cs_vendors":["Ardatan"],"content_html":"\u003cp\u003eThe \u003ccode\u003e@graphql-tools/utils\u003c/code\u003e package (versions 10.10.1 through 12.0.1) contains a prototype pollution vulnerability in the \u003ccode\u003emergeIncrementalResult\u003c/code\u003e function. The function incorrectly validates path segments by using strict equality checks (\u003ccode\u003e===\u003c/code\u003e) against forbidden keys like \u003ccode\u003e'__proto__'\u003c/code\u003e, \u003ccode\u003e'constructor'\u003c/code\u003e, and \u003ccode\u003e'prototype'\u003c/code\u003e. Because the function does not verify that these path segments are primitive types (strings or numbers), an attacker can supply an object, such as an array \u003ccode\u003e[\u0026quot;__proto__\u0026quot;]\u003c/code\u003e. In JavaScript, this is coerced into the string \u003ccode\u003e\u0026quot;__proto__\u0026quot;\u003c/code\u003e during property access, successfully bypassing the protection check and allowing the attacker to write values onto \u003ccode\u003eObject.prototype\u003c/code\u003e. This can lead to authorization bypass, configuration manipulation, or unexpected application behavior in any consuming Node.js process.\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eAn attacker gains control over, or performs a MITM attack on, an upstream GraphQL subgraph or transport layer.\u003c/li\u003e\n\u003cli\u003eThe attacker crafts a malicious incremental GraphQL response (such as an \u003ccode\u003e@defer\u003c/code\u003e or \u003ccode\u003e@stream\u003c/code\u003e patch).\u003c/li\u003e\n\u003cli\u003eThe attacker sets the \u003ccode\u003epath\u003c/code\u003e field in the response to include a non-primitive, array-based segment: \u003ccode\u003e[[\u0026quot;__proto__\u0026quot;], \u0026quot;maliciousKey\u0026quot;]\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe consuming application receives the malicious response and passes it to the public \u003ccode\u003emergeIncrementalResult\u003c/code\u003e helper.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emergeIncrementalResult\u003c/code\u003e calls \u003ccode\u003esetObjectKeyPath\u003c/code\u003e, which checks the array \u003ccode\u003e[\u0026quot;__proto__\u0026quot;]\u003c/code\u003e against the forbidden strings; the check fails (returning false) because the types do not match, allowing the segment to proceed.\u003c/li\u003e\n\u003cli\u003eDuring assignment, \u003ccode\u003ecurrent[key]\u003c/code\u003e triggers \u003ccode\u003eToPropertyKey\u003c/code\u003e coercion, converting the array to the string \u003ccode\u003e\u0026quot;__proto__\u0026quot;\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe function resolves \u003ccode\u003eObject.prototype\u003c/code\u003e and assigns the attacker's value to the chosen key.\u003c/li\u003e\n\u003cli\u003eUnrelated objects created subsequently in the Node.js process inherit the polluted property, altering application logic.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eAn attacker can overwrite properties on \u003ccode\u003eObject.prototype\u003c/code\u003e, potentially impacting global application security controls (e.g., overriding \u003ccode\u003eisAdmin\u003c/code\u003e flags or configuration objects). This effect persists for the lifetime of the Node.js process and applies to all objects instantiated after the pollution event, escaping the scope of the original GraphQL response.\u003c/p\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUpgrade \u003ccode\u003e@graphql-tools/utils\u003c/code\u003e to a patched version once available, or implement a wrapper to validate that all path segments are strictly primitive strings or numbers before calling \u003ccode\u003emergeIncrementalResult\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003eObject.freeze(Object.prototype)\u003c/code\u003e in the consuming Node.js application to mitigate the impact of prototype pollution attempts.\u003c/li\u003e\n\u003cli\u003eImplement runtime input validation on all upstream data sources that provide incremental GraphQL responses.\u003c/li\u003e\n\u003c/ul\u003e\n","date_modified":"2026-10-26T16:13:58Z","date_published":"2026-10-26T16:13:58Z","id":"https://feed.craftedsignal.io/briefs/2026-10-graphql-tools-prototype-pollution-9385e300/","summary":"A prototype pollution vulnerability in @graphql-tools/utils allows an attacker to inject arbitrary properties into Object.prototype via unvalidated path segments in incremental GraphQL responses.","title":"@graphql-tools/utils: Prototype pollution in mergeIncrementalResult","url":"https://feed.craftedsignal.io/briefs/2026-10-graphql-tools-prototype-pollution-9385e300/"}],"language":"en","title":"CraftedSignal Threat Feed - Ardatan","version":"https://jsonfeed.org/version/1.1"}