Broken Access Control in Hanami with Mongodb
Broken Access Control in Hanami with Mongodb — how this specific combination creates or exposes the vulnerability
Broken Access Control occurs when authorization checks are missing or inconsistent, allowing a user to access or modify resources they should not. In Hanami applications that use Mongodb as the persistence layer, this risk is amplified if application-level scopes and filters are not consistently applied across queries. Hanami’s object model and use of repositories encourage explicit query objects, but developers may inadvertently rely on user-supplied identifiers (e.g., :id in routes) to build Mongodb filters without validating that the current subject has the right to access that document.
Consider a typical Hanami endpoint that retrieves a user’s profile by embedding the profile ID in the URL. If the route handler constructs a Mongodb filter as { _id: BSON::ObjectId(params[:id]) } without confirming the profile belongs to the requesting user or that the requesting user has appropriate permissions, an IDOR (Insecure Direct Object Reference) pattern emerges. Because Hanami does not automatically enforce ownership or tenant boundaries at the persistence layer, the onus is on the developer to ensure every Mongodb query incorporates authorization context (e.g., user_id, role, tenant_id). Without such checks, an attacker can iterate through valid ObjectIds and read or modify other users’ data, leading to a BOLA/IDOR finding in a middleBrick scan.
Additionally, Hanami’s use of multiple query classes can inadvertently create inconsistent authorization logic. One repository method might apply a tenant filter, while another omits it when using raw collections or when bypassing the repository via the Unit of Work. If the API endpoint switches between these paths based on feature flags or versioning, the attack surface expands. middleBrick’s checks for BOLA/IDOR and Property Authorization are designed to detect such inconsistencies by correlating OpenAPI path parameters with runtime queries and inspecting whether authorization constraints are reflected in Mongodb filters. The scanner also tests for Privilege Escalation by attempting actions across roles (e.g., a low-privilege user accessing admin-only endpoints) and observes whether Mongodb responses reveal data or errors that indicate missing authorization.
Because Hanami applications often serialize Mongodb documents directly into JSON, excessive data exposure can occur if sensitive fields (password_digest, tokens, internal flags) are included in query results. Even when access is restricted to a specific document, missing field-level filtering in Mongodb projections can leak these fields. middleBrick’s Data Exposure checks look for projections that omit sensitive keys and flag endpoints where responses contain credentials or PII without encryption in transit, tying findings to compliance mappings such as OWASP API Top 10 A01:2027 and GDPR data minimization.
Mongodb-Specific Remediation in Hanami — concrete code fixes
To mitigate Broken Access Control in Hanami with Mongodb, enforce authorization at the point of query construction and ensure every Mongodb filter includes the appropriate scope. Prefer repository methods that embed authorization context rather than building filters ad-hoc in controllers. Below are concrete patterns and code examples.
1. Scope queries by current user
Always include a user_id (or actor identifier) in the filter. If your Hanami app uses a current_user method, pass it into repositories.
# app/repositories/profile_repository.rb
class ProfileRepository
def initialize(user)
@user = user
end
def find(id)
collection.find({ _id: BSON::ObjectId(id), user_id: @user.id }).first
end
end
# app/actions/profiles/show.rb
class Profiles::Show
include Action[:id]
def execute(id)
user = current_user
repo = ProfileRepository.new(user)
@profile = repo.find(id)
halt 404, { error: 'Not found' } unless @profile
end
end
2. Use a base scope for tenant or role-based isolation
For multi-tenant setups, define a module that enforces tenant_id in every filter.
# app/repositories/tenant_scoped_repository.rb
module TenantScopedRepository
def initialize(user)
@user = user
end
def scoped_filter(extra = {})
{ tenant_id: @user.tenant_id }.merge(extra)
end
end
# app/repositories/order_repository.rb
class OrderRepository
include TenantScopedRepository
def list
collection.find(scoped_filter).to_a
end
def find(id)
collection.find(scoped_filter(_id: BSON::ObjectId(id))).first
end
end
3. Apply field-level projection to avoid data exposure
Explicitly exclude sensitive fields in Mongodb queries to prevent accidental leakage.
# app/repositories/user_repository.rb
class UserRepository
def initialize(user)
@user = user
end
def find(id)
collection.find(
{ _id: BSON::ObjectId(id), tenant_id: @user.tenant_id },
{ projection: { email: 1, name: 1, role: 1, _id: 1 } } # excludes password_digest, tokens
).first
end
end
4. Validate ownership in use cases, not just routes
Even when IDs come from trusted sources, verify ownership or permissions inside the use case or service.
# app/actions/comments/create.rb
class Comments::Create
include Action[:post_id]
def execute(post_id)
post = PostRepository.new(current_user).find(post_id)
halt 403, { error: 'Forbidden' } unless post
# proceed to create comment linked to post and current_user
end
end
By embedding authorization in repositories and consistently applying filters, you reduce the risk of BOLA/IDOR and privilege escalation. middleBrick’s checks for Authentication, BOLA/IDOR, Property Authorization, and Data Exposure will validate that your scoped queries and projections are present at runtime, and its findings include remediation guidance tied to frameworks such as OWASP API Top 10.