HIGH api key exposurefeathersjspostgresql

Api Key Exposure in Feathersjs with Postgresql

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

FeathersJS is a framework for building REST and real-time APIs with Node.js. When it interfaces with Postgresql, developers often store service configuration, including API keys, in database tables alongside application data. This practice can lead to Api Key Exposure when query results or service hooks unintentionally expose sensitive fields to clients.

FeathersJS services map database rows to JSON responses. If a service for a config table returns rows that contain columns such as api_key or secret, and the service does not explicitly remove these fields, a client can retrieve the keys via a standard find or get request. This becomes a realistic exposure path when the service definition lacks a before hook that filters fields or a custom get method that redacts sensitive data.

Another exposure vector arises from Postgresql row-level security (RLS) not being enforced. Developers might assume application-level logic is sufficient, but if RLS policies are absent or misconfigured, a compromised service account with broad SELECT permissions can expose keys that the FeathersJS layer does not anticipate. The framework does not automatically hide columns; it returns whatever the query delivers.

Schema design in Postgresql also contributes. Storing keys in a table without column-level protections, such as masking or restricted access roles, increases risk. If the table contains sensitive metadata and the FeathersJS service queries all columns via select *, the keys will be included in the response by default.

Additionally, error messages from Postgresql can leak information. An improperly handled rejection in a FeathersJS hook might surface raw query errors, including constraint violations or type mismatches, that hint at the presence of key columns. While this does not directly return the key, it provides reconnaissance data that can aid an attacker in refining exploits.

To illustrate, consider a FeathersJS service defined over a service_accounts table with columns id, name, and api_key. A naive implementation might expose the key as follows:

// services/config/config.class.js
class ConfigService {
  async find(params) {
    const { pool } = params;
    const result = await pool.query('SELECT * FROM service_config WHERE name = $1', [params.query.name]);
    return result.rows;
  }
}
module.exports = ConfigService;

In this example, if service_config contains an api_key column, the response will include it. An attacker who gains read access to the service endpoint can obtain the key without authentication.

middleBrick detects such patterns during scanning by correlating OpenAPI/Swagger specifications with runtime behavior, identifying endpoints where sensitive fields may be returned. This is particularly relevant when scanning APIs that integrate FeathersJS with Postgresql, as findings can highlight missing redaction or overly permissive data access.

Postgresql-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on ensuring that sensitive columns are never included in responses and that database interactions respect least privilege. Below are concrete code examples for securing a FeathersJS service that uses Postgresql.

First, explicitly select only safe columns in your queries. Avoid SELECT * and instead list required fields:

// services/config/config.class.js
class ConfigService {
  async find(params) {
    const { pool } = params;
    const result = await pool.query(
      'SELECT id, name, created_at FROM service_config WHERE name = $1',
      [params.query.name]
    );
    return result.rows;
  }
}
module.exports = ConfigService;

Second, implement a before hook to remove sensitive fields from the query context. This ensures that even if the query inadvertently includes a sensitive column, it is stripped before execution:

// services/config/config.hooks.js
const { iff, isProvider } = require('feathers-hooks-common');
const removeApiKey = context => {
  if (context.params.provider) {
    delete context.params.query.api_key;
  }
  return context;
};
module.exports = {
  before: {
    all: [iff(isProvider('external'), removeApiKey)]
  },
  after: {
    all: [iff(isProvider('external'), context => {
      context.result.data = context.result.data.map(({ api_key, ...row }) => row);
      return context.result;
    })]
  }
};

Third, enforce column-level security in Postgresql by creating a restricted view and granting access to a limited role:

-- In psql
CREATE VIEW service_config_public AS
SELECT id, name, created_at
FROM service_config;

REVOKE ALL ON TABLE service_config FROM app_user;
GRANT SELECT ON service_config_public TO app_user;

Then point your FeathersJS service at the view instead of the base table. This physically separates sensitive columns from application access.

Fourth, handle errors without exposing internal structure. Use generic error messages in FeathersJS hooks and log detailed Postgresql errors server-side only:

// services/config/config.class.js
async get(id, params) {
  try {
    const { pool } = params;
    const result = await pool.query(
      'SELECT id, name, created_at FROM service_config WHERE id = $1',
      [id]
    );
    return result.rows[0];
  } catch (error) {
    console.error('Config fetch error:', error);
    throw new Error('Unable to retrieve configuration');
  }
}

These steps align with secure coding practices and reduce the likelihood of Api Key Exposure when FeathersJS operates over Postgresql.

middleBrick can validate these patterns by scanning your API endpoints and flagging responses that include sensitive fields. If you use the CLI, you can run middlebrick scan <url> to receive a report that highlights potential exposure. Teams on the Pro plan can enable continuous monitoring to detect regressions, and the GitHub Action can fail builds if a scan detects risky endpoints before deployment.

Frequently Asked Questions

How can I verify that my FeathersJS service does not return API keys in responses?
Use middleBrick to scan your endpoint; review the findings for exposed fields. Additionally, write integration tests that assert the JSON response schema does not contain keys such as api_key or secret.
Does using environment variables for database credentials prevent Api Key Exposure in FeathersJS with Postgresql?
Environment variables protect connection strings but do not affect query responses. You must still ensure that queries do not select sensitive columns and that responses are filtered, as credentials and data exposure are separate concerns.