HIGH broken access controlhanamidynamodb

Broken Access Control in Hanami with Dynamodb

Broken Access Control in Hanami with Dynamodb — how this specific combination creates or exposes the vulnerability

Broken Access Control occurs when authorization checks are missing or bypassed, allowing one user to act on another user's resources. In a Hanami web application using Amazon DynamoDB as the persistence layer, this risk is amplified if object-level permissions are enforced only in the application layer and not validated against the data model.

Hanami encourages explicit domain modeling, but developers sometimes map DynamoDB tables directly to aggregates without scoping queries by the current user. For example, a PostRepository that loads items by ID without confirming ownership can be exploited via IDOR (Insecure Direct Object References). An attacker can iterate over known IDs or guess UUIDs to access posts belonging to other users.

DynamoDB’s attribute-based access control (ABAC) via IAM policies can mitigate this, but only if policies are tightly scoped to the requester’s identity. If the Hanami app assumes the backend enforces permissions and the DynamoDB policy is permissive, the unauthenticated attack surface increases. The scanner checks for missing authorization at the endpoint and data-layer boundaries, flagging endpoints that accept user-supplied identifiers without verifying they belong to the requesting user.

Real-world attack patterns include changing numeric IDs in query parameters, manipulating JWT-sub claims, or reusing session tokens across tenants. The middlebrick LLM/AI Security checks also probe for endpoints that expose model outputs containing sensitive data, which can occur if error messages from DynamoDB are not sanitized.

Using the OpenAPI/Swagger spec analysis, middlebrick cross-references path parameters and request body schemas with runtime behavior. If an endpoint accepts post_id without a matching scope filter (e.g., user_id = :user_id), it will surface as a BOLA/IDOR finding with severity High and remediation guidance to enforce ownership checks.

Dynamodb-Specific Remediation in Hanami — concrete code fixes

To secure Hanami with DynamoDB, enforce ownership checks at the repository level and scope IAM policies to the authenticated user. Below are concrete, working examples that align with DynamoDB best practices and Hanami’s domain-driven design.

1. Scoped query in a Hanami repository

Always include the user identifier in the query key condition. This ensures DynamoDB returns only items the user is allowed to access.

require "dynamodb"

class PostRepository
  def initialize(table_name = "posts")
    @client = Aws::DynamoDB::Client.new
    @table = table_name
  end

  # Fetch a post only if it belongs to the current user
  def find_by_id_for_user(post_id, user_id)
    resp = @client.get_item(
      table_name: @table,
      key: {
        pk: { s: "USER##{user_id}" },
        sk: { s: "POST##{post_id}" }
      }
    )
    item = resp.item
    return nil if item.empty?

    # Map DynamoDB attribute values to domain entity
    Post.new(id: item["sk"].s.split("##").last,
             title: item["title"].s,
             body: item["body"].s,
             author_id: item["user_id"].s)
  end
end

2. IAM policy scoped to user-specific partition keys

Define a policy that restricts each user to their own partition key. This complements application-level checks and reduces the impact of misconfigured endpoints.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:Query"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/posts",
      "Condition": {
        "ForAllValues:StringEquals": {
          "dynamodb:LeadingKeys": ["${cognito-identity.amazonaws.com:sub}"]
        }
      }
    }
  ]
}

3. Hanami endpoint with explicit ownership validation

In the operation class, ensure the current user context is used to scope the repository call. Avoid exposing raw IDs in responses that could be leveraged for horizontal escalation.

class Web::Posts::Show
  include Hanami::Action

  def handle_request(params)
    user_id = current_user.id
    post_id = params[:id]

    post = PostRepository.new.find_by_id_for_user(post_id, user_id)
    if post
      Response::Ok.new(post)
    else
      Response::NotFound.new({ error: "Post not found or access denied" })
    end
  end
end

4. Use DynamoDB condition expressions for additional safety

When updating or deleting, add a condition that the user_id attribute matches the authenticated user. This prevents race conditions where permissions change between read and write.

@client.update_item(
  table_name: @table,
  key: { pk: { s: "USER##{user_id}" }, sk: { s: "POST##{post_id}" } },
  update_expression: "SET #title = :title",
  condition_expression: "user_id = :uid",
  expression_attribute_names: { "#title" => "title" },
  expression_attribute_values: {
    ":title" => { s: new_title },
    ":uid" => { s: user_id }
  }
)

By combining scoped repository methods, tightly scoped IAM policies, and condition expressions, the risk of Broken Access Control in Hanami with DynamoDB is significantly reduced. middlebrick validates these controls through its 12 security checks, including BOLA/IDOR and Property Authorization, to ensure sensitive data exposure and privilege escalation are flagged early.

Frequently Asked Questions

How does middlebrick detect Broken Access Control in Hanami with DynamoDB?
It tests unauthenticated and authenticated scenarios for missing ownership checks, reviews OpenAPI specs for missing scope parameters, and cross-references DynamoDB IAM policy definitions to identify overly permissive resource access.
Can DynamoDB conditional writes fully prevent access control issues?
Conditional writes help prevent race conditions but are not a substitute for consistent authorization checks at read time. Always validate ownership on each request and scope IAM policies to the authenticated user's partition key.