flawopen.com/Prototype Pollution/Object.assign()
क्या Object.assign() Prototype Pollution से सुरक्षित है?
पूरी तरह नहीं। Object.assign() source की अपनी enumerable properties को target पर assign करके कॉपी करता है। यदि source में अपनी enumerable __proto__ key हो, तो assignment inherited setter को चला सकता है और target object का prototype बदल सकता है। केवल shallow assign से साझा Object.prototype नहीं बदलता; recursive merge का प्रभाव अधिक व्यापक हो सकता है।
// A JSON own "__proto__" key reaches the inherited setter const source = JSON.parse('{"__proto__":{"isAdmin":true}}'); const target = Object.assign({}, source); // target's prototype changes; Object.prototype does not. // Recursive merge can reach Object.prototype function deepAssign(target, source) { for (const key of Object.keys(source)) { if (source[key] && typeof source[key] === 'object') { target[key] = target[key] || {}; deepAssign(target[key], source[key]); // With key === '__proto__', target[key] can be // Object.prototype; recursion then writes into it. } else { Object.assign(target, { [key]: source[key] }); } } }
// Spread creates an own data property; it does not invoke the setter. const shallow = { ...userInput }; // Reject dangerous keys at every depth and use own data properties. const blocked = new Set(['__proto__', 'constructor', 'prototype']); function isRecord(value) { if (value === null || typeof value !== 'object' || Array.isArray(value)) return false; const proto = Object.getPrototypeOf(value); return proto === Object.prototype || proto === null; } function copySafe(value) { if (Array.isArray(value)) return value.map(copySafe); return isRecord(value) ? mergeSafe(value) : value; } function mergeSafe(source, target = Object.create(null)) { if (!isRecord(source)) throw new TypeError('Expected a plain object'); for (const key of Object.keys(source)) { if (blocked.has(key)) continue; const value = source[key]; const current = Object.hasOwn(target, key) ? target[key] : undefined; const next = isRecord(value) ? mergeSafe(value, isRecord(current) ? current : Object.create(null)) : copySafe(value); Object.defineProperty(target, key, { value: next, enumerable: true, writable: true, configurable: true }); } return target; }
__proto__ key पर Object.assign() का व्यवहार
Object.assign() target के सामान्य property-setting व्यवहार से source की हर own enumerable property कॉपी करता है। यदि JSON से बने source में own __proto__ property हो और target inherited पुराने setter को प्राप्त करता हो, तो setter target का [[Prototype]] बदल देता है। इस स्थिति में literal own __proto__ property नहीं बनती।
Object spread ({ ...source }) परिणाम में data property बनाता है; वही key own data property बनती है और inherited setter नहीं चलाती। shallow copy के लिए यह उपयोगी अंतर है, लेकिन बाद के recursive merge से सामान्य सुरक्षा नहीं।
Recursive merge साझा prototypes को कैसे प्रदूषित कर सकता है
असुरक्षित recursive code जब attacker-controlled keys का अनुसरण करके साझा prototype में लिखता है, तब Prototype Pollution होता है। आम pattern nested object खोजने के लिए target[key] पढ़ता है। key यदि __proto__ हो, तो यह Object.prototype लौटा सकता है; अगला recursive write सामान्य objects को व्यापक रूप से प्रभावित कर सकता है। constructor.prototype जैसे रास्ते भी जाँचें।
Review में attacker-controlled keys से target पढ़ने या लिखने वाले operations ढूँढें, देखें कि क्या वे setters चलाते हैं, और सुनिश्चित करें कि हर recursive स्तर खतरनाक keys अस्वीकार करे।
अक्सर पूछे जाने वाले प्रश्न
{ ...obj }) भी उतना ही सुरक्षित है?Shallow copy के लिए हाँ: spread own data property बनाता है और inherited setter नहीं चलाता। इसके विपरीत, Object.assign() enumerable source key __proto__ मिलने पर target prototype बदल सकता है। इनमें से कोई भी shallow operation अकेले साझा Object.prototype नहीं बदलता।
structuredClone() अलग copy बनाता है और source की prototype chain लागू नहीं करता। own __proto__ data key copy में data ही रहती है; बाद का असुरक्षित merge फिर भी उसे विशेष रूप से समझ सकता है।
ऐसी merge library चुनें जिसका रखरखाव और अपडेट जारी हो; हर nesting स्तर पर __proto__, constructor और prototype के व्यवहार की जाँच करें। कई लोकप्रिय merge और object-path utilities के लिए Prototype Pollution advisories आई हैं; fix केवल patched versions में होता है।