Skip to content

BUG - Prototype Pollution Vulnerabilities in @sap-ux__project-access #4536

@dfzysmy2tf-create

Description

@dfzysmy2tf-create

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:

  • [✅] Mac OS
  • Windows
  • Other

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).

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