HIGH beast attacksailsfirestore

Beast Attack in Sails with Firestore

Beast Attack in Sails with Firestore — how this specific combination creates or exposes the vulnerability

A Beast Attack (Binding Exception, Adapter Specific) in a Sails.js application that uses Google Cloud Firestore can occur when user-supplied data is used to dynamically reference or instantiate adapters, models, or record bindings without strict validation. In this context, the attack leverages insecure data binding between the Sails ORM-like layer and Firestore to read or write to unintended collections or documents.

Firestore stores data in documents within collections. If a Sails controller accepts a collectionName or documentId from the client and uses it directly to construct a Firestore path, an attacker can manipulate these values to access or modify sensitive documents. For example, a naive implementation might do Firestore.collection(req.param('collection')).doc(req.param('id')), allowing an attacker to change collection to an administrative collection or change id to another user’s record.

This becomes a security issue when Sails models are mapped to Firestore collections dynamically. If the mapping is not strictly enforced, an attacker can perform BOLA (Broken Level Authorization) by iterating through identifiers or escalating privileges by targeting administrative collections. Because Firestore rules are enforced at the database level, improper binding in the application can bypass intended logical segregation between user data.

An attacker may also exploit insecure deserialization or template strings to inject malicious references. For instance, concatenating user input into Firestore paths without normalization or allowlisting enables unintended traversal across collections. The lack of input validation on identifiers used to bind to Firestore collections or documents directly facilitates this class of vulnerability.

middleBrick scanning a Sails + Firestore API can detect these issues by analyzing the unauthenticated attack surface for BOLA and improper binding patterns. The scanner checks whether document and collection identifiers are controlled by the attacker and whether access patterns align with least-privilege expectations, highlighting findings such as Insecure Direct Object References (IDOR) and missing authorization checks.

Firestore-Specific Remediation in Sails — concrete code fixes

To prevent Beast Attacks in Sails with Firestore, enforce strict allowlisting and binding of collections and documents. Never directly use user input to determine collection or document names. Use server-side constants and validate identifiers against a known set of permissible values.

Below are concrete, secure code examples for Sails with Firestore.

1. Fixed Collection Binding with Allowlist

Define a mapping from safe model identifiers to Firestore collections. Validate the incoming collection key against this mapping before creating a reference.

// api/controllers/RecordController.js
const ALLOWED_COLLECTIONS = {
  'user': 'users',
  'post': 'posts',
  'comment': 'comments'
};

module.exports = {
  findOne: async function (req, res) {
    const rawCollection = req.param('collection');
    const rawId = req.param('id');

    if (!rawCollection || !rawId) {
      return res.badRequest('collection and id are required');
    }

    const collectionName = ALLOWED_COLLECTIONS[rawCollection];
    if (!collectionName) {
      return res.forbidden('collection not allowed');
    }

    const db = require('firebase-admin').firestore();
    const docRef = db.collection(collectionName).doc(rawId);
    const snapshot = await docRef.get();

    if (!snapshot.exists) {
      return res.notFound();
    }

    return res.ok(snapshot.data());
  }
};

2. Parameterized Document Access with Ownership Check

When accessing user-specific data, bind the document ID to the authenticated user’s ID rather than trusting the client-supplied ID. Use Firestore security rules in production, but also enforce ownership in application code.

// api/controllers/ProfileController.js
module.exports = {
  me: async function (req, res) {
    const userId = req.me.id; // from session/auth
    const db = require('firebase-admin').firestore();
    const docRef = db.collection('users').doc(userId);
    const snapshot = await docRef.get();

    if (!snapshot.exists) {
      return res.notFound();
    }

    return res.ok(snapshot.data());
  }
};

3. Strict Input Validation and Normalization

Validate identifiers to ensure they conform to expected patterns (e.g., alphanumeric, UUID). Avoid using raw input in Firestore paths. Use normalization functions to prevent path traversal-like behaviors.

// api/services/firestoreSafe.js
const safeDocumentId = (id) => {
  if (!id || typeof id !== 'string') return null;
  // Allow only alphanumeric and underscores, typical for Firestore doc IDs
  return id.replace(/[^a-zA-Z0-9_-]/g, '');
};

module.exports = { safeDocumentId };

Combine these practices with runtime scans using middleBrick to continuously verify that no insecure binding remains in your Sails + Firestore API surface.

Frequently Asked Questions

How can I test if my Sails API with Firestore is vulnerable to a Beast Attack?
Use middleBrick to scan your API. It checks for insecure direct object references and improper binding by analyzing unauthenticated endpoints and comparing runtime behavior against your OpenAPI spec, flagging cases where user-controlled input influences Firestore collection or document references.
Does Firestore security rules alone prevent Beast Attacks in Sails?
Firestore rules are necessary but not sufficient if your Sails application constructs database paths using unchecked user input. Rules can limit access, but application-side binding errors may expose collections or documents. Secure binding logic and input validation in Sails are required alongside rules.