Bola Idor in Sails with Cockroachdb
Bola Idor in Sails with Cockroachdb — how this combination creates or exposes the vulnerability
Broken Object Level Authorization (BOLA) occurs when an API exposes one user’s data by allowing direct manipulation of object identifiers such as IDs or slugs. In Sails.js, this often arises when a controller action looks up a record using a raw ID from request parameters without confirming that the record belongs to the requesting user or tenant. Using CockroachDB as the backend can increase the likelihood of exposure when developers assume strong consistency or transactional guarantees prevent race conditions, leading to incomplete authorization checks.
Consider a Sails controller that retrieves a user’s profile by ID:
module.exports = {
getUserProfile: async function (req, res) {
const userId = req.param('id');
const profile = await User.findOne(userId);
if (!profile) return res.notFound();
return res.ok(profile);
}
};
If the route is /profile/:id and the client changes id to another valid integer, CockroachDB will return the record if it exists, regardless of ownership. Sails Waterline ORM does not automatically scope queries to the requesting user, so the developer must enforce ownership. With CockroachDB, there is no built-in ownership; the database is neutral. Without explicit checks, an attacker can enumerate IDs (horizontal BOLA) or escalate to another user’s data (vertical BOLA).
Another common pattern is using a URL-friendly slug instead of an integer ID:
module.exports = {
getArticle: async function (req, res) {
const slug = req.param('slug');
const article = await Article.findOne({ slug });
if (!article) return res.notFound();
return res.ok(article);
}
};
An attacker can modify the slug to access articles belonging to other authors. Cockroachdb’s distributed SQL nature does not mitigate this; it simply means lookups remain fast and consistent across nodes. The vulnerability is in the lack of contextual authorization, not in the database.
BOLA is frequently listed in the OWASP API Top 10 and can map to compliance frameworks such as PCI-DSS and SOC2. In a multi-tenant Sails application on CockroachDB, failing to scope queries by tenant_id or user_id allows horizontal movement across accounts. Even if the ORM provides associations, the developer must explicitly include the owning user or tenant in every lookup to prevent unauthorized access.
Cockroachdb-Specific Remediation in Sails — concrete code fixes
Remediation centers on ensuring every data access includes explicit ownership or tenant scoping and validating that the requesting user has permission. In Sails, this means enriching query dictionaries with the user’s identity and avoiding reliance on implicit object-level permissions.
First, always include the user identifier in the query. For integer IDs:
module.exports = {
getUserProfile: async function (req, res) {
const userId = req.param('id');
const profile = await User.findOne({ id: userId, userId: req.user.id });
if (!profile) return res.notFound();
return res.ok(profile);
}
};
For slugs, include both the slug and the user context:
module.exports = {
getArticle: async function (req, res) {
const slug = req.param('slug');
const article = await Article.findOne({ slug, authorId: req.user.id });
if (!article) return res.notFound();
return res.ok(article);
}
};
If your User model uses UUIDs, ensure the lookup uses the correct type and index:
module.exports = {
getSettings: async function (req, res) {
const userId = req.user.id; // string UUID
const settings = await UserSettings.findOne({ userId });
if (!settings) return res.notFound();
return res.ok(settings);
}
};
For broader protection, define a policy that attaches the current user to req:
// api/policies/attachUser.js
module.exports = async function attachUser(req, res, next) {
try {
const user = await User.findOne({ apiKey: req.headers['x-api-key'] });
if (!user) return res.unauthorized('Invalid API key');
req.user = user;
return next();
} catch (err) {
return res.serverError(err);
}
};
Then in config/policies.js assign this policy to relevant routes. Cockroachdb does not change how policies are applied; it simply provides a consistent backend while Sails enforces scoping. Combine this with validation libraries to ensure IDs and slugs are properly formatted before querying.
middleBrick can support this workflow by scanning endpoints for missing ownership checks and mapping findings to OWASP API Top 10 and compliance frameworks. Using the CLI (middlebrick scan <url>) or GitHub Action, you can detect BOLA risks in CI/CD before deployment. The dashboard helps track improvements over time, and the MCP Server allows quick scans from your IDE while writing Sails controllers against Cockroachdb.
Related CWEs: bolaAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-250 | Execution with Unnecessary Privileges | HIGH |
| CWE-639 | Insecure Direct Object Reference | CRITICAL |
| CWE-732 | Incorrect Permission Assignment | HIGH |