Broken Access Control in Hapi with Mongodb
Broken Access Control in Hapi with Mongodb — how this specific combination creates or exposes the vulnerability
Broken Access Control in a Hapi application using Mongodb often arises when route-level authorization is incomplete and database-level permissions are misaligned. Hapi provides request-scoping and authorization plugins, but developers must explicitly enforce ownership and role checks; otherwise an authenticated user can modify or retrieve records that belong to another user.
Consider a typical CRUD pattern where an endpoint uses request.auth.credentials.userId to identify the actor. If the handler builds a query by directly interpolating this ID into a filter without validating scope or tenant boundaries, an attacker can manipulate parameters (e.g., changing an ID in the URL or query string) to access or update other users’ documents. This is a classic BOLA/IDOR pattern and is among the checks run by middleBrick’s BOLA/IDOR and Property Authorization tests.
With Mongodb, additional risk appears when the application relies on client-side filtering instead of server-side projection and validation. For example, if a handler uses a broad { userId: id } filter but the database user has broader read permissions, or if the filter omits tenant or role fields, an attacker may leverage injection techniques to escalate visibility. Injection can include dot notation to traverse nested fields or operator injection to bypass intended filters, leading to unauthorized data exposure.
Real-world attack patterns mirror findings in the OWASP API Top 10 and can be detected by middleBrick’s active scanning, which tests for IDOR by probing predictable identifiers and checking whether responses reference data outside the requester’s scope. When Hapi routes do not enforce strict ownership and Mongodb permissions are not scoped to the principle of least privilege, the unauthenticated or low-privilege actor can read or modify sensitive records.
Compliance mappings such as OWASP API Top 10 (A01:2023) and SOC2 highlight the importance of robust access controls. MiddleBrick’s scans include checks for BOLA/IDOR, Property Authorization, and Unsafe Consumption to surface these gaps. Continuous monitoring in the Pro plan can alert teams when endpoints regress, and the GitHub Action can fail builds if a new route lacks sufficient authorization checks.
Mongodb-Specific Remediation in Hapi — concrete code fixes
To secure Hapi routes with Mongodb, enforce ownership at the data access layer and avoid broad or dynamic filters that an attacker can manipulate. Always derive filters from trusted request context and validate identifiers against the authenticated subject.
Example: a safe handler that ensures users can only access their own profiles and posts.
// routes/profile.js
'use strict';
const { ObjectId } = require('mongodb');
exports.register = (server, options, next) => {
server.route({
method: 'GET',
path: '/profile/{id}',
options: {
auth: 'session',
handler: async (request, h) => {
const userId = request.auth.credentials.userId;
const profileId = request.params.id;
// Enforce ownership: do not rely on client-provided filter alone
if (userId !== profileId) {
return h.response({ error: 'Forbidden' }).code(403);
}
const db = request.server.mongo.db;
const result = await db.collection('profiles').findOne({
_id: new ObjectId(profileId),
userId: new ObjectId(userId) // scope to the authenticated user
}, {
projection: { email: 0, passwordHash: 1 }
});
if (!result) {
return h.response({ error: 'Not found' }).code(404);
}
return result;
}
}
});
};
exports.register.attributes = {
name: 'route-profile'
};
Example: a safe handler for listing a user’s posts with explicit scope and projection.
// routes/posts.js
'use strict';
const { ObjectId } = require('mongodb');
exports.register = (server, options, next) => {
server.route({
method: 'GET',
path: '/posts',
options: {
auth: 'session',
handler: async (request, h) => {
const userId = request.auth.credentials.userId;
const db = request.server.mongo.db;
const posts = await db.collection('posts').find({
userId: new ObjectId(userId),
status: 'published'
}, {
projection: { title: 1, body: 1, updatedAt: 1 }
}).sort({ updatedAt: -1 }).toArray();
return posts;
}
}
});
};
exports.register.attributes = {
name: 'route-posts'
};
Additional defensive practices:
- Use a dedicated database user with scoped permissions (read/write only on required collections) so even if filters are bypassed, the DB enforces boundaries.
- Validate ObjectId format before using it in queries to prevent injection via malformed identifiers.
- Apply field-level projection to avoid returning sensitive fields inadvertently.
- Log authorization failures for audit without exposing details to the client.
These patterns align with the remediation guidance provided by middleBrick findings, which map to frameworks such as OWASP API Top 10 and PCI-DSS. The Pro plan’s continuous monitoring can track endpoint behavior over time, and the CLI allows you to script checks during development.