Express.js Remote Property Injection

High Risk Injection
expressproperty-injectionprototype-pollutionjavascriptobject-manipulation

What it is

The Express.js application is vulnerable to remote property injection where user-controlled input can modify object properties, potentially leading to prototype pollution, access control bypass, or code execution. This occurs when user input is used to dynamically set object properties without proper validation.

// Vulnerable: Direct property assignment from user input
app.post('/update-config', (req, res) => {
  const config = {};
  const updates = req.body;
  
  for (const key in updates) {
    config[key] = updates[key]; // Dangerous: can pollute prototype
  }
  
  res.json({ success: true });
});
// Secure: Property validation and safe assignment
const ALLOWED_PROPERTIES = ['name', 'email', 'preferences'];

app.post('/update-config', (req, res) => {
  const config = Object.create(null); // No prototype
  const updates = req.body;
  
  for (const key in updates) {
    if (ALLOWED_PROPERTIES.includes(key) && 
        typeof key === 'string' && 
        !key.includes('__proto__') && 
        !key.includes('constructor')) {
      config[key] = updates[key];
    }
  }
  
  res.json({ success: true });
});

💡 Why This Fix Works

The vulnerable code was updated to address the security issue.

Why it happens

Express.js applications use user-controlled input directly as object property names without validation or sanitization. This allows attackers to set arbitrary properties including special properties like __proto__ or constructor, leading to prototype pollution.

Root causes

Direct User Input as Property Names

Express.js applications use user-controlled input directly as object property names without validation or sanitization. This allows attackers to set arbitrary properties including special properties like __proto__ or constructor, leading to prototype pollution.

Unvalidated Dynamic Property Assignment

Code dynamically assigns properties to objects based on user input (e.g., obj[userInput] = value) without checking if the property name is safe. This enables attackers to modify object behavior by setting dangerous properties.

Unsafe Bracket Notation Usage

Applications use JavaScript bracket notation with user input to access or modify object properties without verifying the property name. Attackers can exploit this to access or modify protected properties, prototype chains, or internal object methods.

Missing Prototype Pollution Defenses

Code lacks protections against prototype pollution attacks where attackers modify Object.prototype or other prototypes through property injection. No checks prevent assignment to __proto__, constructor.prototype, or other dangerous property paths.

Unrestricted Object Merging Operations

Applications use object merge/extend operations (Object.assign, spread operator, lodash merge) with user-controlled objects without filtering dangerous properties. This allows attackers to inject malicious properties into target objects.

Fixes

1

Validate and Sanitize Property Names

Implement strict validation for all user-controlled property names before using them. Check against dangerous property names including __proto__, constructor, prototype, and use regular expressions to ensure only safe alphanumeric property names. Reject or sanitize any input that doesn't match expected patterns.

2

Implement Property Name Allowlists

Create and enforce allowlists of permitted property names for dynamic property assignment. Use a whitelist approach where only explicitly approved property names can be set, rejecting all others. This prevents attackers from accessing or modifying unexpected object properties.

3

Freeze or Seal Critical Objects

Use Object.freeze() to make critical objects completely immutable or Object.seal() to prevent new properties from being added while allowing existing properties to be modified. Apply these protections to configuration objects, prototypes, and other sensitive objects that shouldn't be modified at runtime.

4

Use Map Objects for Dynamic Properties

Replace plain JavaScript objects with Map objects when storing user-controlled key-value pairs. Maps don't have prototype chains and can safely store any keys without risk of prototype pollution or property injection attacks.

5

Implement Safe Object Merging

Before merging or extending objects with user input, validate the object structure and filter out dangerous properties. Use libraries with safe merge functions or implement custom merge logic that explicitly blocks __proto__, constructor, and prototype properties.

6

Use Safe Property Setting Libraries

Utilize security-focused libraries like lodash's set() method with proper path validation, or implement wrapper functions that validate property paths before assignment. Avoid direct bracket notation with unsanitized user input.

Detect This Vulnerability in Your Code

Sourcery automatically identifies express.js remote property injection and many other security issues in your codebase.