hi, we are a security team. We found a Prototype Pollution vulnerability in your project.
Related Feature
Feature request:6
Description
A series of prototype pollution vulnerabilities exist in the @sap-ux__project-access package, allowing attackers to inject malicious proto keys into user-controlled input paths/objects. These keys trigger dynamic property writes or unsafe object merging logic (without hasOwnProperty checks), resulting in pollution of the global Object.prototype and potential arbitrary code execution or application behavior modification.
Steps to Reproduce
Steps to reproduce the behavior:
1.
Call the addPackageDevDependency function with a malicious depName parameter set to proto and a payload in depVersion.
Example: await lib.addPackageDevDependency('/tmp/test-project', 'proto', { 'polluted': true }, {})
Verify Object.prototype.polluted is set to true.
2.
Create a malicious project/application directory with i18n property/model files named proto (or containing proto as a key in JSON).
Call createProjectAccess/createApplicationAccess with the path to the malicious directory:
await lib.createProjectAccess('/path/to/malicious/project', {})
await lib.createApplicationAccess('/path/to/malicious/app', {})
Verify prototype pollution via Object.prototype.polluted.
3.
Create a project directory with i18n configurations containing proto keys.
Call findAllApps with the malicious project path: await lib.findAllApps('/path/to/malicious/project', {})
Check for prototype pollution.
4.
Pass a JSON-parsed options object with proto to createProjectAccess/createApplicationAccess:
await lib.createProjectAccess('/tmp/test-project', JSON.parse('{"proto": {"polluted": true}}'))
await lib.createApplicationAccess('/tmp/test-project', JSON.parse('{"proto": {"polluted": true}}'))
The for-in loop in ui5-config.js (line 82) merges the proto key into the prototype chain without validation.
Expected results
User-controlled input (file names, dynamic property keys, options objects) should not modify the global Object.prototype.
Dynamic property writes and object merging logic should sanitize/block proto, constructor, and prototype keys to prevent prototype pollution.
Unsafe iteration (for-in loops) should include hasOwnProperty checks to avoid iterating over prototype properties.
Actual results
Object.prototype is polluted with attacker-controlled values (e.g., polluted: true).
Global prototype pollution can lead to unintended behavior in all object instances (e.g., broken property checks, arbitrary code execution if other parts of the application rely on untrusted object properties).
No validation or sanitization of proto keys in user-controlled input paths/objects.
Version/Components/Environment
Add any other context about the problem here
OS:
Root Cause Analysis
Problem
Unsanitized Dynamic Property Writes: User-controlled input (e.g., depName, file/key names from i18n files) is directly used as a dynamic property name in object assignments (e.g., packageJson.devDependencies[depName], result.models[key]). If the input is proto, this modifies the global prototype chain.
Unsafe Object Merging: The ui5-config.js file uses a for-in loop to merge options into default configurations without checking hasOwnProperty. This allows proto keys (from parsed JSON) to be iterated and assigned to Object.prototype.
Lack of Input Sanitization: No validation/blocking of reserved prototype-related keys (proto, constructor, prototype) in user-controlled input paths or objects.
Fix
Sanitize Dynamic Property Names:
Block or escape reserved keys (proto, constructor, prototype) before using them in dynamic property writes.
Example: Replace proto with a safe alternative (e.g., proto) or throw an error if reserved keys are detected.
Add hasOwnProperty Checks:
Modify for-in loops (e.g., in ui5-config.js) to check obj.hasOwnProperty(key) before processing:
for (const key in options) {
if (options.hasOwnProperty(key)) {
// Safe merging logic
}
}
Use Prototype-Safe Objects:
Create objects with Object.create(null) (no prototype) for dynamic property storage (e.g., result.models = Object.create(null)), so proto acts as a normal key instead of modifying the global prototype.
Validate User-Controlled Paths/Inputs:
Scan file/directory names and JSON keys for reserved prototype keys and reject/normalize them before processing (e.g., in createProjectAccess, createApplicationAccess, findAllApps).
hi, we are a security team. We found a Prototype Pollution vulnerability in your project.
Related Feature
Feature request:6
Description
A series of prototype pollution vulnerabilities exist in the @sap-ux__project-access package, allowing attackers to inject malicious proto keys into user-controlled input paths/objects. These keys trigger dynamic property writes or unsafe object merging logic (without hasOwnProperty checks), resulting in pollution of the global Object.prototype and potential arbitrary code execution or application behavior modification.
Steps to Reproduce
Steps to reproduce the behavior:
1.
Call the addPackageDevDependency function with a malicious depName parameter set to proto and a payload in depVersion.
Example: await lib.addPackageDevDependency('/tmp/test-project', 'proto', { 'polluted': true }, {})
Verify Object.prototype.polluted is set to true.
2.
Create a malicious project/application directory with i18n property/model files named proto (or containing proto as a key in JSON).
Call createProjectAccess/createApplicationAccess with the path to the malicious directory:
await lib.createProjectAccess('/path/to/malicious/project', {})
await lib.createApplicationAccess('/path/to/malicious/app', {})
Verify prototype pollution via Object.prototype.polluted.
3.
Create a project directory with i18n configurations containing proto keys.
Call findAllApps with the malicious project path: await lib.findAllApps('/path/to/malicious/project', {})
Check for prototype pollution.
4.
Pass a JSON-parsed options object with proto to createProjectAccess/createApplicationAccess:
await lib.createProjectAccess('/tmp/test-project', JSON.parse('{"proto": {"polluted": true}}'))
await lib.createApplicationAccess('/tmp/test-project', JSON.parse('{"proto": {"polluted": true}}'))
The for-in loop in ui5-config.js (line 82) merges the proto key into the prototype chain without validation.
Expected results
User-controlled input (file names, dynamic property keys, options objects) should not modify the global Object.prototype.
Dynamic property writes and object merging logic should sanitize/block proto, constructor, and prototype keys to prevent prototype pollution.
Unsafe iteration (for-in loops) should include hasOwnProperty checks to avoid iterating over prototype properties.
Actual results
Object.prototype is polluted with attacker-controlled values (e.g., polluted: true).
Global prototype pollution can lead to unintended behavior in all object instances (e.g., broken property checks, arbitrary code execution if other parts of the application rely on untrusted object properties).
No validation or sanitization of proto keys in user-controlled input paths/objects.
Version/Components/Environment
Add any other context about the problem here
OS:
Root Cause Analysis
Problem
Unsanitized Dynamic Property Writes: User-controlled input (e.g., depName, file/key names from i18n files) is directly used as a dynamic property name in object assignments (e.g., packageJson.devDependencies[depName], result.models[key]). If the input is proto, this modifies the global prototype chain.
Unsafe Object Merging: The ui5-config.js file uses a for-in loop to merge options into default configurations without checking hasOwnProperty. This allows proto keys (from parsed JSON) to be iterated and assigned to Object.prototype.
Lack of Input Sanitization: No validation/blocking of reserved prototype-related keys (proto, constructor, prototype) in user-controlled input paths or objects.
Fix
Sanitize Dynamic Property Names:
Block or escape reserved keys (proto, constructor, prototype) before using them in dynamic property writes.
Example: Replace proto with a safe alternative (e.g., proto) or throw an error if reserved keys are detected.
Add hasOwnProperty Checks:
Modify for-in loops (e.g., in ui5-config.js) to check obj.hasOwnProperty(key) before processing:
Use Prototype-Safe Objects:
Create objects with Object.create(null) (no prototype) for dynamic property storage (e.g., result.models = Object.create(null)), so proto acts as a normal key instead of modifying the global prototype.
Validate User-Controlled Paths/Inputs:
Scan file/directory names and JSON keys for reserved prototype keys and reject/normalize them before processing (e.g., in createProjectAccess, createApplicationAccess, findAllApps).