HIGH prototype pollutionfeathersjscockroachdb

Prototype Pollution in Feathersjs with Cockroachdb

Prototype Pollution in Feathersjs with Cockroachdb — how this specific combination creates or exposes the vulnerability

Prototype pollution in a Feathersjs service using Cockroachdb typically arises when user-supplied input is merged into service-side objects that later influence database operations, query construction, or metadata. Feathersjs is a framework that favors a service-oriented design where each service exposes methods such as create, update, and patch. If these methods directly merge untrusted data onto JavaScript objects that are used to build queries or modify behavior, an attacker can inject properties into Object.prototype or other shared prototypes, affecting subsequent operations across requests.

When Cockroachdb is the backend, the risk does not stem from the database itself introducing prototype pollution, but from how Feathersjs code constructs parameters, query filters, or options before sending them to Cockroachdb. For example, if a service does Object.assign({}, req.query) or spreads user input into a query filter without sanitization, an attacker can supply properties like __proto__, constructor.prototype.polluted, or nested paths that affect object behavior in Node.js runtime. These poisoned prototypes can cause unexpected truthiness, altered iteration behavior, or bypass of validation checks when the Feathersjs app processes data before forwarding to Cockroachdb.

Consider a Featherjs service that builds a WHERE clause dynamically from user input:

// Risky: directly using user input to construct query parts
app.service('reports').hooks({
  before: {
    create: [context => {
      const { filters } = context.data;
      // If filters is user-controlled and merged without validation,
      // prototype pollution can alter Object.prototype behavior.
      context.params.query = { ...filters };
      return context;
    }]
  }
});

If filters contains a malicious payload such as { "__proto__": { isAdmin: true } }, the spread can pollute the prototype chain, potentially affecting how other objects are interpreted later in the request lifecycle, including how query options are passed to Cockroachdb drivers. Cockroachdb drivers typically expect well-typed query parameters; unexpected properties may not cause direct injection, but they can change logical behavior when combined with insecure object handling in the application layer.

Another vector involves parameter tampering in update operations. A service that applies partial updates using user-provided data without deep validation can expose prototype pollution:

app.service('users').patch(id, data, {
  query: { select: 'id,name' }
});

If data includes a polluted property that mutates shared objects used to construct the update payload, runtime behavior can change in subtle ways, including modifying headers, altering request context, or influencing how the Cockroachdb connection interprets options. This can lead to privilege escalation or data exposure even when the database itself receives only intended column updates.

Prototype pollution in this stack is fundamentally an application-layer concern, but it can amplify risks when combined with Cockroachdb because the polluted objects may affect how queries are built, how transactions are configured, or how results are processed. Attackers do not need to exploit a Cockroachdb-specific flaw; they exploit insecure handling of objects that eventually inform database interactions.

Cockroachdb-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on strict input validation, avoiding prototype-mutable operations, and isolating user data from query construction. Below are concrete Feathersjs patterns that reduce risk when working with Cockroachdb.

1. Validate and sanitize all user input before merging

Use a library such as Ajv to validate incoming data against a strict schema. Do not spread or assign user data directly onto objects that may affect prototype chains.

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);

const reportSchema = {
  type: 'object',
  properties: {
    filters: {
      type: 'object',
      additionalProperties: true
    }
  },
  required: ['filters'],
  additionalProperties: false
};

const validate = ajv.compile(reportSchema);

app.service('reports').hooks({
  before: {
    create: [context => {
      if (!validate(context.data)) {
        throw new Error('Invalid data');
      }
      // Use a safe clone to avoid mutating user input
      context.params.query = JSON.parse(JSON.stringify(validate.errors));
      return context;
    }]
  }
});

2. Use safe object construction instead of spread or Object.assign

Avoid { ...userObject } when userObject may contain prototype-manipulating keys. Prefer explicit extraction or libraries that strip dangerous keys.

function safeQueryFromUser(input) {
  const safe = {};
  if (input && typeof input === 'object' && !Array.isArray(input)) {
    Object.keys(input).forEach(key => {
      if (key !== '__proto__' && key !== 'constructor' && key !== 'prototype') {
        safe[key] = input[key];
      }
    });
  }
  return safe;
}

app.service('items').hooks({
  before: {
    update: [context => {
      context.params.query = safeQueryFromUser(context.data);
      return context;
    }]
  }
});

3. Parameterize Cockroachdb queries to avoid injection and pollution side effects

Use parameterized queries or an ORM that enforces separation between code and data. This prevents injected properties from altering query structure.

const { Client } = require('pg'); // Cockroachdb compatible driver

app.service('todos').hooks({
  before: {
    create: [async context => {
      const client = new Client({
        connectionString: process.env.DATABASE_URL
      });
      await client.connect();
      const { title, userId } = context.data;
      // Use parameterized query; user input never becomes SQL text
      const result = await client.query(
        'INSERT INTO todos (title, user_id) VALUES ($1, $2) RETURNING *',
        [title, userId]
      );
      context.data = result.rows[0];
      await client.end();
      return context;
    }]
  }
});

4. Harden object handling in hooks and services

Ensure that internal objects used for query building are created fresh and are not reused across requests. Avoid attaching data to Object.prototype or shared constructors.

// Safe pattern: create a plain object per request
app.service('search').hooks({
  before: {
    find: [context => {
      const safeParams = {
        filter: Object.freeze(context.query.filter || {}),
        pagination: {
          skip: Number.isFinite(context.query.skip) ? context.query.skip : 0,
          limit: Number.isFinite(context.query.limit) ? context.query.limit : 10
        }
      };
      context.params.query = safeParams;
      return context;
    }]
  }
});

5. Apply middleware to detect common pollution indicators

Add lightweight checks to flag suspicious keys before they reach services.

app.hooks({
  before: {
    all: [context => {
      const hasProtoPollution = (obj) => {
        if (!obj || typeof obj !== 'object') return false;
        return Object.prototype.hasOwnProperty.call(obj, '__proto__') ||
               Object.prototype.hasOwnProperty.call(obj, 'constructor') ||
               Object.prototype.hasOwnProperty.call(obj, 'prototype');
      };
      const traverse = (obj) => {
        if (hasProtoPollution(obj)) throw new Error('Potential prototype pollution detected');
        if (obj && typeof obj === 'object') {
          Object.values(obj).forEach(traverse);
        }
      };
      traverse(context.data);
      traverse(context.query);
      return context;
    }]
  }
});

Frequently Asked Questions

Can prototype pollution enable SQL injection against Cockroachdb?
Prototype pollution in Feathersjs does not directly enable SQL injection if queries are parameterized. However, pollution can alter query-building logic, potentially leading to unsafe query construction. Always use parameterized queries or an ORM and validate input.
Does middleBrick detect prototype pollution in API payloads?
middleBrick runs 12 security checks in parallel, including Input Validation, which tests for common injection and pollution patterns. While it does not actively exploit prototype pollution, it can surface related findings in the Input Validation category with remediation guidance. To scan an endpoint, use middlebrick scan via CLI or the Web Dashboard.