HIGH clickjackinghanamifirestore

Clickjacking in Hanami with Firestore

Clickjacking in Hanami with Firestore — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side UI redress attack where an attacker tricks a user into interacting with a hidden or disguised element inside an invisible or overlaying page. In a Hanami application that uses Google Cloud Firestore as a backend, this can occur when pages render data from Firestore without enforcing frame isolation. An attacker can embed the Hanami page inside an <iframe> and overlay interactive controls, causing a logged-in user to inadvertently perform Firestore-backed actions such as updating records or invoking server-side methods.

Hanami follows the model–view–controller pattern and typically renders views with embedded partials. If these views include forms or state-changing buttons without explicit frame-busting headers or sandboxing, they remain vulnerable even when Firestore data is correctly retrieved. The Firestore integration is not directly responsible for clickjacking, but the way Hanami templates bind Firestore documents to UI elements can amplify the impact: a user may click what appears to be a benign element, while a hidden form submits a PATCH request that updates Firestore documents based on the user’s permissions.

Because Firestore security rules operate at the authentication and authorization level, they do not prevent clickjacking. A user with valid credentials can still be socially engineered into performing unwanted writes. The risk is especially relevant when Hanami exposes Firestore collections through REST-like routes or when server-rendered forms include document IDs in hidden fields. Without anti-CSRF tokens and without explicit X-Frame-Options or Content-Security-Policy frame-ancestors directives, an attacker can craft a page that loads the Hanami endpoint and captures interactions.

Real-world examples align with common OWASP categories such as A05:2021 — Security Misconfiguration and A08:2021 — Software and Data Integrity Failures. For instance, a Hanami route like /projects/:id/update_status that accepts PATCH requests and directly maps parameters to Firestore document fields becomes a target if embedded maliciously. Attack patterns involving multiple chained UI actions (e.g., toggle visibility, then submit) are feasible when clickjacking vectors are not mitigated at the rendering layer.

Firestore-Specific Remediation in Hanami — concrete code fixes

Remediation centers on breaking the ability of external pages to control interactions within your Hanami views and ensuring that Firestore-bound actions require explicit intent. The following practices and code examples assume you use the google-cloud-firestore gem within a Hanami controller and view layer.

1. Anti-clickjacking headers

Configure your web server or Rack middleware to send X-Frame-Options and Content-Security-Policy headers. In a Hanami app, you can add these in application.rb or via middleware configuration.

# config/initializers/security_headers.rb
module MyApp
  class Application < Hanami::Application
    configure do |config|
      config.middleware.use Rack::Protection::FrameOptions
    end
  end
end

Alternatively, set headers explicitly per route or globally to restrict framing:

# config/initializers/csp.rb
Rack::Protection::FrameOptions.override_action = ->(env) { [200, { 'Content-Security-Policy' => "frame-ancestors 'self'" }, []] }

2. Embed Firestore reads safely and avoid hidden state

When displaying Firestore data, avoid placing mutable actions inside iframes or partial templates that could be overlaid. Use explicit tokens and ensure Firestore document reads are tied to the current user context.

# app/controllers/projects/show.rb
require "google/cloud/firestore"

class Projects::Show
  include Hanami::Action

  def initialize(firestore_client: nil)
    @firestore = firestore_client || Google::Cloud::Firestore.new
  end

  def call(params)
    project = @firestore.doc("projects/#{params[:id]}").get
    halt 404, 'Not found' unless project.exists?

    @project_data = {
      id: project.id,
      name: project[:name],
      status: project[:status]
    }

    # Render a view that uses @project_data directly, without hidden form fields for sensitive operations
    view.render("projects/show", @project_data)
  end
end

3. Require anti-CSRF tokens for state-changing requests

Ensure that any POST, PATCH, or DELETE originating from Firestore-backed views includes a per-session or per-request token. Hanami provides built-in protection that you should enable.

# app/controllers/projects/update.rb
class Projects::Update
  include Hanami::Action

  def call(params)
    # Hanami verifies authenticity token automatically when config.session_options[:skip] is not used
    project = Google::Cloud::Firestore.new.doc("projects/#{params[:id]}").get
    halt 403, 'Forbidden' unless project.exists?

    # Safe update using only permitted params
    updated = project.update(params.fetch(:project, {}).slice(:status, :owner))
    flash[:success] = 'Project updated'
    redirect_to routes.projects_path
  end
end

4. Avoid exposing Firestore document IDs in URLs and UI without checks

When Firestore document IDs are reflected in UI elements, ensure they are scoped to the current user and validated server-side to prevent direct object-level authorization bypasses (BOLA/IDOR) that could be leveraged inside a clickjacking context.

# app/views/projects/show.html.erb
<form action="<%= routes.projects_update_path(project_id: @project_data[:id]) %>" method="post">
  <input name="_csrf_token" value="<%= session_csrf_token %>">
  <button type="submit">Update Status</button>
</form>

Frequently Asked Questions

Can Firestore security rules alone prevent clickjacking in Hanami?
No. Firestore security rules validate authentication and data access but do not protect against UI redress attacks. You must implement anti-frame headers and anti-CSRF measures in Hanami to prevent clickjacking.
How does middleBrick relate to clickjacking detection in Hanami with Firestore?
middleBrick scans unauthenticated attack surfaces and can surface misconfigurations such as missing frame-ancestors directives or overly permissive CORS settings. It does not fix these issues but provides remediation guidance aligned with frameworks like OWASP API Top 10.