tezvyn:

Prototype pollution: how it works and prevention

AI-drafted, machine-checkedSource: interviewadvanced
WHAT IT TESTS

Deep JS object-model security.

OUTLINE

Attacker writes to Object.prototype via __proto__ keys in merge/parse code, poisoning all objects; prevent by guarding keys, null-prototype objects, Object.freeze, Map, and patched deps.

WHAT THIS TESTS: Whether you understand that JavaScript objects share a mutable prototype, and how attacker-controlled keys can corrupt it globally with security consequences.

A GOOD ANSWER COVERS: Almost every object inherits from Object.prototype. Prototype pollution is when an attacker manages to assign a property onto that shared prototype, so the new property leaks into every object that does not override it. The usual vector is an unsafe operation that copies attacker-controlled keys into an object, such as a recursive deep-merge, a deep-clone, or a set-by-path utility, where a key like __proto__ or constructor.prototype is followed instead of being treated as a literal property. Parsing JSON containing a __proto__ key and then merging it is a classic trigger. Consequences range from changing application defaults (a polluted isAdmin or an injected default), to denial of service, to remote code execution when polluted properties feed into template rendering or child_process options. Defenses span code and dependencies: explicitly reject or skip __proto__, constructor, and prototype keys in any merge; create lookup objects with Object.create(null) so they have no prototype; use Map instead of plain objects for user-keyed data; Object.freeze(Object.prototype) to make it immutable; validate input against a strict schema; prefer JSON.parse with care and avoid vulnerable merge libraries; and run npm audit to patch known-pollutable dependencies.

COMMON WRONG ANSWERS: Confusing it with normal prototypal inheritance; thinking it only affects one object instance rather than all objects; believing TypeScript types prevent it (they do not exist at runtime); assuming JSON.parse alone is dangerous (the merge step is the usual culprit).

LIKELY FOLLOW-UPS: How does pollution escalate to RCE? Why does Object.create(null) help? How do Node's newer protections and --disable-proto flag fit in? Which popular libraries had CVEs for this?

ONE CONCRETE EXAMPLE: A handler deep-merges req.body into config. An attacker posts {"__proto__": {"isAdmin": true}}. The merge walks into the prototype and sets isAdmin on Object.prototype, so an unrelated user object that never set isAdmin now reads true, granting privilege escalation across the app.

Read the original → cheatsheetseries.owasp.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.