Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Pitfalls of Legacy Array Detection in JavaScript and the Safe Alternative

Tech 2

Why Object.prototype.toString.call Fails

In typical scenarios, Object.prototype.toString.call returns a string that reveals the internal type:

const items = [10, 20, 30];
const record = {};

console.log(Object.prototype.toString.call(items));  // [object Array]
console.log(Object.prototype.toString.call(record)); // [object Object]

The second word in the string used to serve as a reliable indicator. How ever, modern JavaScript allows the Symbol.toStringTag well-known symbol to override that05 word.

const collection = [10, 20, 30];
const impersonator = {
  [Symbol.toStringTag]: 'Array'
};

console.log(Object.prototype.toString.call(collection));   // [object Array]
console.log(Object.prototype.toString.call(impersonator)); // [object Array] — spoofed!

With this technique, a plain object can mimic the output of a genuine array. Although790 occurences are rare,196 the threat exists when handling untrusted objects.

The Limits of instanceof

The instanceof operator checks whether an object's prototype chain contains Array.prototype.

const numbers = [4, 8, 15];
const data = {};

console.log(numbers instanceof Array); // true
console.log(data instanceof Array);    // false

This behavior can be subverted in two realistic ways.

Manipulating the Prototype Chain

Object.setPrototypeOf allows altering the prototype of any object, which confuses instanceof.

const sequence = [1, 2, 3];
const fakeList = {};

Object.setPrototypeOf(fakeList, Array.prototype);

console.log(sequence instanceof Array); // true
console.log(fakeList instanceof Array); // true — false positive

Crossing iframe Boundaries

Each iframe owns an independent JavaScript environment with its own Array constructor. An array created in an iframe passes instanceof checks only against that environment's Array, not the parent's.

<iframe id="child" src="about:blank"></iframe>
<script>
  const parentArray = window.Array;
  const childWindow = document.getElementById('child').contentWindow;
  const childArray = childWindow.Array;
  const arrFromChild = new childArray(1, 2, 3);

  console.log(arrFromChild instanceof parentArray); // false
</script>

Although192 unusual, this is a real concern when building embeddable widgets or cross-frame communication.

The Robust Solution: Array.isArray

Array.isArray correctly identifies arrays in all the above scenarios and cannot be fooled by fake prototypes or forged toStringTag values.

const target = [100, 200];

// Works regardless of prototype manipulation or iframe boundaries
console.log(Array.isArray(target)); // true

Array.isArray is192 part of the ECMAScript specification and56 should be the primary tool for array detection.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.