HIGH vulnerable componentsfeathersjsfirestore

Vulnerable Components in Feathersjs with Firestore

Vulnerable Components in Feathersjs with Firestore — how this specific combination creates or exposes the vulnerability

FeathersJS is a framework for real-time APIs that typically exposes services through REST and WebSocket endpoints. When FeathersJS uses Google Cloud Firestore as a service adapter, developers often configure service hooks and queries that inadvertently create authorization and validation vulnerabilities. A common pattern is mapping incoming query parameters directly to Firestore queries without sanitization, which can enable BOLA/IDOR and BFLA through relaxed ownership checks.

Consider a FeathersJS service defined with the Firebase adapter, where the before hook does not enforce record ownership. An attacker can manipulate query filters to access documents they should not see, because Firestore rules may be permissive for read operations while the application layer lacks strict tenant or user scoping. This misalignment between Firestore security rules and FeathersJS service logic results in insecure direct object references, a key vector in OWASP API Top 10 Broken Object Level Authorization.

Input validation weaknesses emerge when FeathersJS passes untrusted parameters into Firestore queries. For example, a where clause built from user-controlled fields without type or enum validation can be coerced into returning sensitive data or triggering errors that leak schema details. Firestore’s index and query flexibility may allow unintended field access if the application does not explicitly restrict which fields are queryable.

Property-level authorization gaps arise when Firestore documents contain privileged fields such as isAdmin or role. If FeathersJS returns entire documents to the client, these fields may be exposed even when they should be restricted. This contributes to data exposure and can violate compliance mappings such as PCI-DSS and SOC2, which require strict segregation of privilege-sensitive attributes.

Finally, unsafe consumption patterns occur when FeathersJS services accept raw request bodies and directly write them to Firestore without schema enforcement. Missing content-type validation and field sanitization can lead to injection-like behaviors or document structure corruption. Combined with missing rate limiting, this may allow rapid document writes that resemble abuse or enumeration, triggering noisy alerts but not preventing misuse.

Firestore-Specific Remediation in Feathersjs — concrete code fixes

To secure FeathersJS with Firestore, enforce strict ownership checks in hooks and parameterize queries to avoid dynamic filter building from user input. Below is a hardened FeathersJS service setup that demonstrates these principles.

const feathers = require('@feathersjs/feathers');
const express = require('@feathsjs/express');
const {Firestore} = require('@google-cloud/firestore');
const {FirestoreService} = require('feathers-google-firestore');

const app = feathers();
const firestore = new Firestore();

app.configure(express.json());

// Helper to extract user ID from authenticated request
const getUserId = (params) => {
  if (params && params.user && params.user.userId) {
    return params.user.userId;
  }
  throw new Error('Unauthenticated');
};

// Custom before hook to enforce ownership and strict filtering
app.use('/messages', {
  async before(hook) {
    const userId = getUserId(hook.params);

    // Ensure query is scoped to the requesting user
    if (hook.params.query) {
      hook.params.query.where = hook.params.query.where || [];
      // Append tenant/user filter if not already present
      const hasUserFilter = hook.params.query.where.some(
        cond => cond.field === 'userId' && cond.op === '==' && cond.value === userId
      );
      if (!hasUserFilter) {
        hook.params.query.where.push({ field: 'userId', op: '==', value: userId });
      }
    } else {
      hook.params.query = { where: [{ field: 'userId', op: '==', value: userId }] };
    }

    // Explicitly limit returned fields to avoid privilege escalation via property exposure
    if (!hook.params.query.select) {
      hook.params.query.select = ['id', 'text', 'userId', 'createdAt'];
    }
    return hook;
  },

  // Use the Firestore service adapter
  service: FirestoreService({
    Model: firestore.collection('messages')
  }),

  // After hook to remove sensitive fields before sending response
  after: {
    all: [async (hook) => {
      if (Array.isArray(hook.result.data)) {
        hook.result.data = hook.result.data.map((record) => {
          const { isAdmin, role, ...safe } = record;
          return safe;
        });
      } else if (hook.result.data) {
        const { isAdmin, role, ...safe } = hook.result.data;
        hook.result.data = safe;
      }
      return hook;
    }]
  }
});

// Example of a parameterized query that avoids raw user input in field names
app.service('/messages').hooks({
  before: {
    async find(hook) {
      const { userId } = hook.params.query;
      if (userId) {
        // Validate userId format before using it
        if (!/^[A-Za-z0-9_-]{1,20}$/.test(userId)) {
          throw new Error('Invalid user identifier');
        }
        // Firestore query with explicit field and value
        hook.params.query.where = [
          { field: 'userId', op: '==', value: userId }
        ];
      }
      return hook;
    }
  }
});

These examples show how to bind Firestore queries to a user context, limit returned fields, and validate identifiers to prevent injection and privilege escalation. For compliance mappings, ensure that findings from middleBrick scans are reviewed against OWASP API Top 10 and relevant regulatory controls; middleBrick’s dashboard and CLI reports can help track these issues over time.

Additionally, enable Firestore rules that mirror application-level constraints, such as allowing reads only when request.auth.uid matches the document’s userId field. Combine this with middleBrick’s continuous monitoring in the Pro plan to detect regressions in your API security posture as your FeathersJS service evolves.

Frequently Asked Questions

How can I prevent Firestore documents from exposing sensitive fields when using FeathersJS?
Use an after hook in FeathersJS to strip sensitive fields such as isAdmin or role before sending the response. Define an allowlist of safe fields and ensure Firestore rules also restrict read access to privileged attributes.
Can middleBrick help detect Firestore-related authorization issues in FeathersJS services?
Yes, middleBrick scans unauthenticated attack surfaces and includes checks for BOLA/IDOR and property authorization. Its dashboard and CLI reports can highlight findings relevant to OWASP API Top 10 and compliance frameworks, helping you track and prioritize fixes.