How Lodash isNative Bypasses Overridden Functions

Lodash’s _.isNative utility function determines whether a target function is a genuine host-environment built-in rather than a userland polyfill or an overridden implementation. This article examines the internal mechanisms Lodash uses to achieve this, including isolating pristine prototype methods, dynamically generating engine-tailored regular expressions, and detecting hidden metadata flags from third-party polyfills to ensure functions are evaluated securely without executing untrusted code.

The Problem with Naive Function Verification

In JavaScript, functions can be monkey-patched or assigned custom properties. A naive check for a native function often looks like this:

function isNative(fn) {
  return fn.toString().includes('[native code]');
}

This approach has critical vulnerabilities:

  1. Method Overriding: If a function object defines its own toString method (e.g., fn.toString = () => "function () { [native code] }"); it can easily deceive the caller.
  2. Engine Discrepancies: Different JavaScript engines format native function representations differently (for instance, differences between V8, SpiderMonkey, and JavaScriptCore).

Bypassing Instance-Level toString Hijacking

To prevent a function from forging its own string representation, Lodash does not call the method on the target instance directly. Instead, it captures and uses the original, unmutated Function.prototype.toString method:

const fnToString = Function.prototype.toString;

// Invocation
fnToString.call(value);

By explicitly invoking the native Function.prototype.toString with .call(value), Lodash completely bypasses any custom .toString properties an attacker or library may have placed directly onto the function instance.

Dynamic Regular Expression Generation

Different JavaScript environments output variations of native functions. Rather than relying on a hardcoded string or static pattern, Lodash builds a dynamic regular expression tailored to the host environment at load time.

Lodash generates this expression by converting a known native function—Object.prototype.hasOwnProperty—to a string and escaping special characters:

const reIsNative = RegExp(
  '^' +
  fnToString.call(Object.prototype.hasOwnProperty)
    .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
    .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') +
  '$'
);

This dynamic pattern captures the precise format used by the current engine while replacing the function name with a wildcard pattern (.*?). When an arbitrary function is passed into _.isNative, its string representation via Function.prototype.toString.call(value) must match this engine-specific template exactly.

Detecting Polyfill Masking

Modern polyfill libraries like core-js often attempt to hide their presence by spoofing Function.prototype.toString to return [native code]. To prevent false positives, Lodash inspects the function for internal masking flags.

When core-js replaces or wraps a native method, it typically leaves a metadata fingerprint on the global environment or function instance:

const coreJsData = root['__core-js_shared__'];
const maskFunctionKey = coreJsData ? coreJsData.keys && coreJsData.keys.IE_PROTO : '';

function isMasked(func) {
  return !!maskFunctionKey && (maskFunctionKey in func);
}

Lodash checks whether a function contains these masking markers. If a function matches the native regular expression but has been flagged by a polyfill framework, Lodash rejects it as non-native.

Handling Host Objects and Proxies

In addition to string inspection, _.isNative incorporates basic type validation:

While ES2015 Proxy objects cannot be completely distinguished from native functions if explicitly configured to mimic them at the prototype level, Lodash's multi-layered strategy protects against common override techniques, monkey-patching, and polyfill impersonation.