HIGH broken access controlsailscockroachdb

Broken Access Control in Sails with Cockroachdb

Broken Access Control in Sails with Cockroachdb — how this specific combination creates or exposes the vulnerability

Broken Access Control in a Sails application backed by CockroachDB typically occurs when authorization checks are missing, incomplete, or bypassed at the API and model layers. Sails models that directly expose REST endpoints can leak records if policies do not enforce record-level ownership or tenant boundaries. With CockroachDB, the risk is amplified in multi-tenant setups where tenant identifiers are stored in columns but not consistently enforced in every query. If a Sails controller or model relies only on request parameters (e.g., id) to fetch a record without verifying that the record belongs to the requesting user or tenant, an attacker can manipulate IDs to access another user’s data.

CockroachDB’s SQL semantics do not inherently enforce application-level permissions; it executes queries as issued. In Sails, if your Waterline ORM queries are constructed dynamically without scoping by tenant or user, an attacker can exploit predictable or weakly validated identifiers. For example, an endpoint like GET /user/:id that loads a user by ID without ensuring the authenticated user’s ID matches :id becomes a BOLA (Broken Object Level Authorization) vector. Cockroachdb’s strong consistency and distributed nature may also expose race conditions or timing differences that make ID enumeration more reliable when access controls are absent.

Common OWASP API Top 10 mappings include A01:2023 (Broken Object Level Authorization) and A07:2023 (Identification and Authentication Failures). Real-world attack patterns involve changing numeric or UUID identifiers in requests to enumerate or modify resources. Without proper authorization checks at the model or controller level, an API that exposes user profiles, orders, or documents via predictable IDs is vulnerable. middleBrick scans detect these issues by correlating OpenAPI/Swagger specs with runtime behavior, identifying endpoints where parameters such as userId or recordId are not constrained by the authenticated subject’s permissions.

Cockroachdb-Specific Remediation in Sails — concrete code fixes

To remediate Broken Access Control in Sails with CockroachDB, enforce tenant and ownership scoping in every database query. Define a policy that adds a tenantId (or userId) filter to all Waterline queries, and validate the subject on each request. Below are concrete, syntactically correct examples using the CockroachDB adapter for Sails.

1. Scoped model queries with tenant isolation

Ensure every find, update, and delete includes a tenant identifier taken from the authenticated session. Never rely on the client-supplied ID alone.

// api/controllers/DocumentController.js
module.exports = {
  async findMyDocuments(req, res) {
    const userId = req.me.id; // from session/auth
    try {
      const docs = await Document.find({
        where: {
          tenantId: userId,
          // additional safe filters
        },
        limit: 50,
      });
      return res.ok(docs);
    } catch (err) {
      return res.serverError(err);
    }
  }
};

2. Parameterized query with strict ID validation

When fetching a single record by client-supplied ID, verify ownership before returning data. Use CockroachDB’s parameterized queries via Waterline to avoid injection and enforce row-level permissions.

// api/controllers/ProfileController.js
module.exports = {
  async get(req, res) {
    const userId = req.me.id;
    const inputId = req.param('id');
    if (!inputId || !Number.isInteger(Number(inputId))) {
      return res.badRequest('Invalid identifier');
    }
    const profile = await Profile.findOne({
      id: inputId,
      tenantId: userId,
    }).meta({ cockpit: { disableSafeUpdate: false } });
    if (!profile) {
      return res.notFound();
    }
    return res.ok(profile);
  }
};

3. Policy-based authorization with custom logic

Use Sails policies to centralize access checks. Combine session data with model attributes to decide whether a request should proceed.

// api/policies/tenantOwnership.js
module.exports = async function (req, res, proceed) {
  const model = req.options.model || req.options.controller;
  const allowedAttributes = ['tenantId', 'ownerId'];
  const hasScope = allowedAttributes.some((attr) => req.options.where && attr in req.options.where);
  if (!hasScope) {
    return res.forbidden('Missing ownership scope');
  }
  // Optionally enrich query with session subject if not already present
  if (!req.options.where.tenantId && req.me && req.me.tenantId) {
    req.options.where.tenantId = req.me.tenantId;
  }
  return proceed();
};

4. CockroachDB schema considerations

Define indexes and constraints that support efficient tenant-scoped lookups. A composite index on (tenantId, id) improves performance and ensures queries leverage the intended access path.

-- CockroachDB SQL example for index creation
CREATE INDEX IF NOT EXISTS idx_tenant_id ON tenant_table (tenant_id, id);

Frequently Asked Questions

What is a practical way to enforce tenant isolation in Sails with CockroachDB?
Always scope queries by tenantId derived from the authenticated session and validate incoming IDs. Use Waterline's where to include tenantId: req.me.tenantId on every find, and create a CockroachDB index on (tenantId, id) to enforce and accelerate row-level isolation.
How can middleBrick help detect Broken Access Control in this setup?
middleBrick scans your API endpoints and correlates OpenAPI/Swagger specs with runtime behavior to identify missing authorization checks, such as endpoints that accept user-controlled IDs without verifying tenant or ownership constraints.