HIGH insecure designhanamiapi keys

Insecure Design in Hanami with Api Keys

Insecure Design in Hanami with Api Keys — how this specific combination creates or exposes the vulnerability

Insecure design in a Hanami application that uses API keys often stems from how keys are generated, stored, transmitted, and validated. Hanami, being a lightweight Ruby web framework, does not enforce a specific authentication mechanism out of the box, which means developers must explicitly design secure handling for API keys. Weak design decisions—such as placing keys in query strings, logging them, or embedding them in JavaScript—create opportunities for exposure.

One common pattern is defining a before-action filter that reads an API key from headers and bypasses broader authentication. If this filter is applied inconsistently across endpoints, it can lead to authorization issues where some routes are protected while others are effectively public. For example, a Hanami app might have a global filter in app.rb but forget to apply it to a newly added endpoint, leaving an unauthenticated path to sensitive data or operations.

Another design risk is key storage. Hardcoding API keys in initializers or environment files checked into version control has led to widespread credential leaks. Hanami’s configuration system allows settings to be loaded from config/application.rb or environment-specific files, but if developers place static keys there without using encrypted secrets or environment injection, the keys become part of the repository history.

Transmission design also matters. If API keys are passed in URL query parameters instead of the Authorization header, they can appear in server logs, browser history, and proxy logs, increasing exposure risk. Hanami routes typically map cleanly to controller actions, and if a developer constructs URLs with embedded keys for convenience, they inadvertently create logging and leakage vectors.

Middleware and routing design can compound these issues. Hanami uses Rack middleware stack, and if custom middleware is introduced to handle key validation, bugs in that middleware—such as failing to reject requests with missing or malformed keys—can weaken the overall security model. Additionally, design choices around rate limiting and monitoring—if omitted—allow brute-force or enumeration attacks against key formats to go undetected.

These insecure design patterns map to real-world attack scenarios. For instance, an attacker might discover an exposed API key through source code search or log scraping and then use it to call administrative endpoints that should have been restricted. In a Hanami app with weak segregation between public and private APIs, this could lead to data exfiltration or unauthorized actions, aligning with common weaknesses such as CWE-798 (Use of Hard-coded Credentials) and CWE-287 (Improper Authentication).

Api Keys-Specific Remediation in Hanami — concrete code fixes

Remediation focuses on secure generation, transmission, storage, and validation of API keys within the Hanami framework. Below are concrete code examples that demonstrate a hardened approach.

Secure key generation and storage

Generate API keys using a cryptographically secure random source and store them outside the codebase. Use environment variables or a secrets manager, and avoid committing keys to version control.

# config/initializers/api_keys.rb — do NOT hardcode keys here
# Instead, load from environment
API_KEY = ENV.fetch('HANAMI_API_KEY') { raise 'Missing API key in environment' }

In production, inject the key via your deployment platform (e.g., Docker secrets, Kubernetes secrets, or platform environment settings).

Secure transmission via headers

Always transmit API keys in the Authorization header using a standard scheme such as Bearer or a custom scheme like ApiKey. This reduces logging and exposure risks.

# app/controllers/concerns/api_key_auth.rb
module ApiKeyAuth
  extend ActiveSupport::Concern

  included do
    before :authenticate_api_key
  end

  private

  def authenticate_api_key
    header_key = request.env['HTTP_AUTHORIZATION']
    if header_key&.start_with?('ApiKey ')
      key = header_key.split(' ').last
      halt 401, { error: 'Unauthorized' }.to_json unless key == ENV.fetch('HANAMI_API_KEY')
    else
      halt 401, { error: 'Missing Authorization header' }.to_json
    end
  end
end

# app/api/v1/protected_resource.rb
class V1::ProtectedResource < Hanami::Resource
  include ApiKeyAuth

  get do
    { status: 'ok', message: 'Access granted with valid API key' }
  end
end

Validation and rejection of malformed requests

Explicitly reject requests that lack the key or use an incorrect scheme, and avoid falling back to other authentication mechanisms that could weaken security.

# app/api/v1/admin/users.rb
class V1::AdminUsers < Hanami::Resource
  include ApiKeyAuth

  get do
    # Only reachable if authenticate_api_key passed
    { users: UserRepository.new.public_users }
  end
end

Operational and design best practices

  • Define a single point of key validation to avoid inconsistent application across routes.
  • Log failed attempts without logging the key itself, and monitor for repeated failures.
  • Rotate keys periodically and have a revocation plan that does not require code changes, such as maintaining a denylist stored in a fast lookup (e.g., Redis) if your architecture scales beyond simple env vars.

These measures align with secure design principles by ensuring API keys are treated as high‑sensitivity credentials, reducing the attack surface exposed through insecure routing or storage decisions in Hanami applications.

Frequently Asked Questions

Why is passing API keys in query strings considered insecure in Hanami applications?
Passing API keys in query strings exposes them in server logs, browser history, and proxy logs, increasing the risk of leakage. Hanami routes often include query parameters in logs by default, so keys embedded in URLs can be captured and reused by attackers.
How can I ensure API keys are consistently enforced across all Hanami endpoints?
Use a shared before-action filter or concern that validates the API key on every request and apply it globally in your application configuration. Centralizing validation in one module and including it in all relevant resources prevents accidental public exposure due to missing filters on new endpoints.