Object.hasOwn vs Lodash has for Prototype Pollution

This article examines the core differences between ES2022's native Object.hasOwn() method and Lodash’s _.has() function in the context of prototype pollution defense. It covers how each handles inherited properties, property path traversal, null-prototype objects, and the security implications of using native shallow property checks compared to library-based deep path evaluation.

Shallow Key Checking vs. Path Resolution

The most fundamental architectural difference between Object.hasOwn() and _.has() lies in how keys are parsed and traversed:

Defense Against Polluted Inherited Properties

Both methods are designed to verify whether an object holds an "own" property rather than an inherited one. This distinction is critical when defending against prototype pollution:

Using either method prevents code from mistakenly treating an injected prototype property as a valid, intentional property of the instance.

Handling Null-Prototype Objects and Overrides

Before ES2022, the common idiom obj.hasOwnProperty('prop') suffered from two notable vulnerabilities:

  1. Objects created via Object.create(null) do not inherit from Object.prototype, causing obj.hasOwnProperty to throw a TypeError.
  2. Malicious inputs or polluted prototypes could override the hasOwnProperty method itself with an arbitrary function or property.

Both Object.hasOwn() and _.has() mitigate these failure modes:

Security Guarantees in Input Sanitization

When building defenses to sanitize input keys against prototype pollution attacks:

For validating property ownership at a single layer, native Object.hasOwn() provides a deterministic, zero-dependency, and tamper-resistant security boundary.