HIGH api key exposurefeathersjscockroachdb

Api Key Exposure in Feathersjs with Cockroachdb

Api Key Exposure in Feathersjs with Cockroachdb — how this specific combination creates or exposes the vulnerability

FeathersJS is a framework for real-time applications that often exposes REST and WebSocket endpoints without enforcing authentication on service hooks. When a FeathersJS service is configured to use CockroachDB as its persistence layer, developers may inadvertently expose API keys or service credentials through insecure service definitions, logging, or error handling.

The risk occurs when a Feathers service queries CockroachDB with raw parameters that include sensitive metadata, such as an API key stored in a request query or payload. If the service does not sanitize inputs or enforce authorization rules, an attacker can manipulate the request to retrieve or infer the API key. For example, a misconfigured before hook might pass an API key as a query option directly to CockroachDB, and a verbose error message could reveal the key in a stack trace or log entry.

In a black-box scan, middleBrick checks whether unauthenticated endpoints can leak sensitive data by analyzing input validation, authorization logic, and data exposure paths. If a Feathers service connected to CockroachDB does not apply strict property-level checks, an API key could appear in logs, error responses, or client-side traces, violating data exposure controls.

Additionally, insecure integration patterns—such as embedding API keys in client-side requests or failing to mask sensitive fields in serialized responses—amplify the exposure. middleBrick’s checks for Data Exposure and Unsafe Consumption validate whether API keys are protected during transit and serialization, flagging cases where Cockroachdb query results include sensitive metadata without encryption or truncation.

Cockroachdb-Specific Remediation in Feathersjs — concrete code fixes

To secure a FeathersJS service using CockroachDB, explicitly separate sensitive configuration from request flow and enforce strict input validation and authorization in hooks.

1. Use environment variables for secrets

Store API keys and database credentials outside the codebase. In your Feathers service, reference them via process.env and avoid passing raw keys to CockroachDB queries.

// src/environment.js
module.exports = {
  cockroachdb: {
    connectionString: process.env.COCKROACHDB_CONNECTION_STRING,
    apiKey: process.env.EXTERNAL_API_KEY
  }
};

2. Parameter sanitization in before hooks

Ensure that any user-supplied data used in CockroachDB queries is validated and stripped of sensitive fields before reaching the database.

// src/hooks/sanitize-api-key.js
module.exports = function sanitizeApiKey() {
  return async context => {
    const { params } = context;
    // Remove API key from query if present in payload
    if (params.query && params.query.api_key) {
      delete params.query.api_key;
    }
    // Ensure metadata does not contain raw keys
    if (context.data && context.data.metadata) {
      context.data.metadata = Object.fromEntries(
        Object.entries(context.data.metadata).filter(([key]) => key !== 'api_key')
      );
    }
    return context;
  };
};

3. Secure service configuration with field masking

Configure your Feathers service to exclude sensitive fields from responses and to pass only necessary options to CockroachDB.

// src/services/records/records.service.js
const { Service } = require('feathers-sequelize');
const { cockroachdb } = require('../../environment');

class SecureRecordsService extends Service {
  async find(params) {
    // Call super with sanitized query options
    const result = await super.find({
      ...params,
      // Ensure no API key is forwarded as a query option
      query: {
        ...params.query,
        $select: ['id', 'name', 'createdAt'],
        $mask: { apiKey: '**REDACTED**' }
      }
    });
    return result;
  }
}

module.exports = function () {
  const app = this;
  app.use('/records', new SecureRecordsService({
    Model: require('./records.model'),
    paginate: { default: 10, max: 50 }
  }));

  const recordsService = app.service('records');
  recordsService.hooks({
    before: {
      all: [
        require('./hooks/sanitize-api-key'),
        context => {
          // Example: inject API key from secure env for backend use only
          if (!context.params.query.api_key) {
            context.params.query.api_key = cockroachdb.apiKey;
          }
          return context;
        }
      ],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: []
    },
    after: {
      all: [],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: []
    },
    error: {
      all: [],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: []
    }
  });
};

4. Use parameterized queries and avoid dynamic SQL

When interacting with CockroachDB through an ORM or query builder, prefer parameterized inputs to prevent injection and accidental exposure of keys in logs.

// Example using a parameterized query pattern
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize(cockroachdb.connectionString);

async function getRecordById(id) {
  const record = await sequelize.query(
    'SELECT id, name FROM records WHERE id = :id',
    { replacements: { id }, type: Sequelize.QueryTypes.SELECT }
  );
  return record;
}

These practices reduce the likelihood that API keys or CockroachDB credentials appear in logs, error messages, or client responses, aligning with Data Exposure and Input Validation checks.

Frequently Asked Questions

Can middleBrick prevent API key exposure in FeathersJS with CockroachDB?
middleBrick detects and reports potential API key exposure but does not prevent or fix issues. It provides findings and remediation guidance so you can secure hooks, sanitize inputs, and manage secrets appropriately.
Does scanning with middleBrick require authentication against the FeathersJS service?
No. middleBrick runs unauthenticated black-box scans to test the public attack surface. For deeper authenticated checks, you may provide credentials, but the default scans require no credentials.