__proto__ injection क्या है
मुख्य बात: JSON.parse __proto__ को सामान्य key मानता है; नुकसान उस recursive merge में होता है जो Object.prototype में लिखता है, जिससे हर object हमलावर की properties विरासत में पा लेता है।

मुख्य बात: किसी भी merge से पहले __proto__, constructor और prototype रोकें, अविश्वसनीय input को Object.create(null) में merge करें, और CI में prototype assertion जोड़ें; अकेले लाइब्रेरी patch करना काफ़ी नहीं।
एक वाक्य में: __proto__ नाम की अविश्वसनीय key recursive merge से मिलती है, और merge prototype में लिखता है।
एक reproduction
function merge(target, source) {
for (const key in source) {
if (typeof source[key] === 'object' && source[key] !== null) {
target[key] = target[key] || {};
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
merge({}, JSON.parse('{"__proto__": {"isAdmin": true}}'));
console.log({}.isAdmin); // true
कोई व्यावसायिक object छुआ नहीं गया। Object.prototype छुआ गया, और अब हर object isAdmin लिए हुए है।
JSON.parse दोषी क्यों नहीं है
const data = JSON.parse('{"__proto__": {"a": 1}}');
Object.getOwnPropertyNames(data); // [ '__proto__' ]
Object.getPrototypeOf(data) === Object.prototype; // true, अछूता
__proto__ सामान्य own property के रूप में आता है। ख़तरा पूरी तरह उस code में है जो बाद में merge, deep-copy या path से set करता है — _.merge, कुछ Object.assign पैटर्न, और अनगिनत हाथ से लिखे set(obj, path, value) helpers।
प्रभाव
- Authorisation bypass:
if (user.isAdmin)बिना शर्त true हो जाता है - डेटा भ्रष्टाचार: अनपेक्षित फ़ील्ड संग्रहीत records में serialise हो जाते हैं
- Denial of service: prototype से जुड़े बड़े objects memory को स्थायी रूप से बढ़ा देते हैं
- Escalation: template engines या command runners के साथ मिलकर यह remote code execution तक ले गया है
चार बचाव
Keys filter करें।
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
केवल __proto__ रोकना अपर्याप्त है: constructor.prototype भी उसी जगह पहुँचता है।
Null-prototype object में merge करें।
const safeTarget = Object.create(null);
Prototype chain न होने पर __proto__ बस एक string key है।
in के बजाय Object.hasOwn उपयोग करें। in prototype chain में भी देखता है।
Dependencies patched रखें। lodash, deepmerge और json-patch सभी इस श्रेणी की bug के लिए fixes भेज चुके हैं। npm audit पर नज़र रखें।
जाँचें कि यह ठीक रहता है
__proto__ और constructor वाला payload अपने merge से गुज़ारें, फिर assert करें:
console.log({}.polluted); // undefined
console.log(Object.prototype.polluted); // undefined
CI में एक assertion, लगभग शून्य लागत, बाद के refactors से आने वाले regressions पकड़ लेती है।
FAQ
Merge को कौन सी keys filter करनी चाहिए?
__proto__, constructor और prototype तीनों को साथ रोकें। केवल __proto__ filter करना अपर्याप्त है, क्योंकि constructor.prototype उसी prototype तक पहुँचता है।
Object.create(null) लिखने से कैसे रोकता है?
Null-prototype object में prototype chain नहीं होती, इसलिए __proto__ सामान्य string key रहता है। यह data container के रूप में काम करता है, पर key filtering या dependency अपडेट की जगह नहीं लेता।
CI में prototype pollution की जाँच कैसे करूँ?
__proto__ और constructor वाला payload अपने merge से भेजें, फिर assert करें कि {}.polluted और Object.prototype.polluted undefined हैं। एक assertion लगभग कुछ भी खर्च नहीं करती और बाद के refactors से आने वाले regressions पकड़ लेती है।