Interlace ESLint
ESLint Interlace
Secure CodingRules

detect-object-injection

Detects `variable[key]` as a left- or right-hand assignment operand (prototype pollution). This rule is part of [`eslint-plugin-secure-coding`](https://www.npmj

Keywords: prototype pollution, CWE-915, security, ESLint rule, object injection, bracket notation, property injection, auto-fix, LLM-optimized, code security

Detects variable[key] as a left- or right-hand assignment operand (prototype pollution). This rule is part of eslint-plugin-secure-coding and provides LLM-optimized error messages with fix suggestions.

🚨 Security rule | 💡 Provides LLM-optimized guidance | ⚠️ Set to error in recommended

Quick Summary

AspectDetails
CWE ReferenceCWE-915 (Prototype Pollution)
SeverityCritical (security vulnerability)
Auto-Fix⚠️ Suggests fixes (manual application)
CategorySecurity
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForAll applications, especially those handling user input for object properties

Vulnerability and Risk

Vulnerability: Object injection (specifically Prototype Pollution) occurs when user input is used to access or modify properties of an object, particularly using bracket notation (e.g., obj[userInput]) without validation.

Risk: Attackers can modify critical properties like __proto__, constructor, or prototype, affecting the behavior of all objects in the application. This can lead to Denial of Service (DoS), bypass of security checks, or even Remote Code Execution (RCE) depending on how the polluted properties are used.

Rule Details

This rule detects dangerous use of bracket notation with dynamic property names that can lead to prototype pollution attacks.

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-915 OWASP:A01 CVSS:9.8 | Object Injection detected | CRITICAL [SOC2,PCI-DSS,ISO27001]
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A01_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-915 OWASP:A01 CVSS:9.8
Issue DescriptionSpecific vulnerabilityObject Injection detected
Severity & ComplianceImpact assessmentCRITICAL [SOC2,PCI-DSS,ISO27001]
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Configuration

OptionTypeDefaultDescription
allowLiteralsbooleanfalseAllow bracket notation with literal strings
additionalMethodsstring[][]Additional object methods to check
dangerousPropertiesstring[]['__proto__', 'prototype', 'constructor']Properties to consider dangerous

Examples

❌ Incorrect

// Prototype pollution - CRITICAL risk
obj[userInput] = value; // If userInput is "__proto__", pollutes all objects

// Constructor manipulation - HIGH risk
config[userKey] = func; // If userKey is "constructor", injects methods

// Property injection - MEDIUM risk
settings[dynamicKey] = data; // Uncontrolled property addition

✅ Correct

// Use Map for dynamic key-value storage
const config = new Map<string, any>();
config.set(userKey, value);

// Use Object.create(null) for clean objects
const safeObj = Object.create(null);
safeObj[userKey] = value; // Safe because no prototype

// Property whitelisting
const ALLOWED_KEYS = ['name', 'age', 'email', 'role'];
if (ALLOWED_KEYS.includes(userKey)) {
  obj[userKey] = value;
}

// hasOwnProperty check
if (obj.hasOwnProperty(userKey)) {
  const value = obj[userKey]; // Safe access
}

Prototype Pollution Prevention

Understanding the Attack

// Attacker controls userInput = "__proto__"
// This pollutes ALL objects in the application
obj[userInput] = { malicious: () => console.log('HACKED') };

// Now ALL objects have the malicious property
const innocent = {};
console.log(innocent.malicious); // Function exists!

Safe Alternatives

  1. Map for Key-Value Storage

    const config = new Map<string, any>();
    config.set(userKey, value);
    const value = config.get(userKey);
  2. Object.create(null)

    const safeObject = Object.create(null); // No prototype
    safeObject[userKey] = value;
  3. Property Whitelisting

    const ALLOWED_PROPS = ['name', 'age', 'email'];
    if (ALLOWED_PROPS.includes(prop)) {
      obj[prop] = value;
    }

Security Impact

Prototype Pollution Attacks

// Pollute Object.prototype
const obj = {};
obj[userInput] = maliciousFunction;
// If userInput = "__proto__", ALL objects are polluted

// Constructor injection
obj[userInput] = maliciousConstructor;
// If userInput = "constructor", object creation is compromised

// Property shadowing
Object.prototype[userInput] = maliciousValue;
// All property access can be manipulated

Real-World Impact

  • Data Manipulation - Alter application data structures
  • Method Injection - Add malicious methods to all objects
  • Information Disclosure - Access sensitive object properties
  • Denial of Service - Break application functionality

Migration Guide

Phase 1: Discovery

{
  rules: {
    'secure-coding/detect-object-injection': 'warn'
  }
}

Phase 2: Replace Dynamic Access

// Replace object access
obj[key] → use Map or whitelisting

// Replace assignments
obj[key] = value → map.set(key, value)

Phase 3: Add Validation

// Implement property validation
function isValidProperty(prop: string): boolean {
  const ALLOWED = ['name', 'value', 'type'];
  return ALLOWED.includes(prop) && !prop.startsWith('_');
}

Phase 4: Secure Implementation

// Use secure patterns
const config = new Map();
const safeObj = Object.create(null);

Advanced Protection

Deep Prototype Protection

// Freeze prototypes (careful - affects entire application)
Object.freeze(Object.prototype);
Object.freeze(Array.prototype);

// Or use a security library
import { secureObject } from 'security-utils';
const safeObj = secureObject.create();

Type-Safe Access

// TypeScript: strict property access
interface SafeConfig {
  [key: string]: never; // No index signature
  name: string;
  value: number;
}

const config: SafeConfig = { name: '', value: 0 };
// config[userKey] = value; // TypeScript error!

Testing Security

// Test prototype pollution attempts
const pollutionAttempts = [
  '__proto__',
  'prototype',
  'constructor',
  '__defineGetter__',
  '__defineSetter__',
];

for (const prop of pollutionAttempts) {
  expect(() => {
    const obj = {};
    obj[prop] = 'malicious';
    return obj.hasOwnProperty('malicious');
  }).toBe(false); // Should not pollute
}

Comparison with Alternatives

Featuredetect-object-injectioneslint-plugin-securityeslint-plugin-sonarjs
Prototype Pollution Detection✅ Yes⚠️ Limited⚠️ Limited
CWE Reference✅ CWE-915 included⚠️ Limited⚠️ Limited
LLM-Optimized✅ Yes❌ No❌ No
ESLint MCP✅ Optimized❌ No❌ No
Fix Suggestions✅ Detailed⚠️ Basic⚠️ Basic

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Property from Variable

Why: Property names stored in variables not traced.

// ❌ NOT DETECTED - Property from variable
const prop = userInput;
obj[prop] = value;

Mitigation: Validate keys before any bracket access.

Nested Object Access

Why: Deep property chains not fully analyzed.

// ❌ NOT DETECTED - Nested access
obj.nested[userKey] = value;

Mitigation: Apply whitelisting to all levels.

Object.assign with Spread

Why: Spread of user objects may pollute.

// ❌ NOT DETECTED - Object spread
const result = { ...userObject }; // May contain __proto__

Mitigation: Use safe merge utilities.

JSON.parse Pollution

Why: Parsed JSON can introduce prototype keys.

// ❌ NOT DETECTED - JSON pollution
const obj = JSON.parse(userJson); // May have __proto__

Mitigation: Use JSON.parse with reviver. Filter keys.

Further Reading

On this page