HIGH api key exposurehanamisaml

Api Key Exposure in Hanami with Saml

Api Key Exposure in Hanami with Saml

When Hanami applications integrate SAML for authentication, API keys can be inadvertently exposed through misconfigured attribute handling or debug endpoints. Hanami typically uses environment variables or encrypted secrets for API keys, but SAML responses may introduce additional parameters or session attributes that, if improperly managed, become vectors for exposure.

During SAML authentication, an Identity Provider (IdP) sends assertions containing user attributes. If a Hanami application maps SAML attributes directly to internal objects without validation, sensitive keys stored in the session or used for downstream service authentication might be serialized into logs, URLs, or JavaScript-rendered views. For example, a route that renders the current user’s session as JSON for debugging could return an API key embedded in the session hash:

Hanami.app do
  get '/debug' do
    # Dangerous: exposes session and any attached API keys
    session.to_json
  end
end

Additionally, SAML responses often carry NameID or custom attributes that may be stored in the database or session. If an API key is derived from or linked to these attributes—such as using the user’s email (from SAML) to look up a service key—attackers who can influence the SAML assertion (via account takeover or a malicious IdP) can indirectly access or infer the key. This becomes critical when Hanami uses the key for outbound requests to third-party APIs, as the key may be passed in headers or query parameters that are logged by upstream services.

The risk is compounded if the Hanami app exposes introspection endpoints or uses client-side JavaScript to access session data. An attacker leveraging XSS or a misconfigured CORS policy could read API keys from responses that include SAML-derived user data. Since SAML assertions are often base64-encoded XML, improper parsing may also lead to insecure deserialization, further leaking key material through error messages or logs. The combination of SAML’s broad attribute scope and Hanami’s convention-over-configuration approach increases the surface for accidental key disclosure.

Consider an endpoint that uses a service API key to fetch resources after SAML login:

class ApiClient
  def initialize(user)
    @api_key = user.session_key # potentially derived from SAML attributes
  end

  def fetch_data
    response = HTTP.headers(Authorization: "Bearer #{@api_key}").get('https://api.vendor.com/data')
    JSON.parse(response.body)
  end
end

If the user.session_key originates from a SAML attribute and is exposed in logs or error traces, the API key is compromised. This scenario highlights why Hanami applications must treat SAML attributes as untrusted input and isolate keys from assertion-derived data.

Saml-Specific Remediation in Hanami

Remediation focuses on strict attribute validation, isolation of secrets, and avoiding the propagation of SAML-derived values into key management flows. Hanami provides mechanisms to filter and transform SAML assertions before they touch sensitive objects.

First, explicitly whitelist expected SAML attributes and reject unexpected ones. Do not map arbitrary SAML attributes to internal models or session keys. Instead, extract only the necessary fields (e.g., email for user lookup) and keep API keys stored securely in Hanami’s repository layer, never in session or URL parameters:

# config/initializers/saml.rb
SAML_SETTINGS = {
  idp_cert_fingerprint: ENV['IDP_CERT_FINGERPRINT'],
  issuer: 'https://idp.example.com',
  attribute_mapping: {
    email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'
  }
}

# In your session handler, only allow known attributes
class SamlSession
  def initialize(response)
    raise 'Invalid SAML response' unless valid_attributes?(response.attributes)
    @email = response.attributes['email']
  end

  private

  def valid_attributes?(attrs)
    allowed = SAML_SETTINGS[:attribute_mapping].keys.map(&:to_s)
    (attrs.keys.map(&:to_s) - allowed).empty?
  end
end

Second, ensure API keys are retrieved from a secure store independent of SAML data. Use Hanami’s dependency injection to pass keys explicitly, avoiding any linkage to user-supplied attributes:

class ApiClient
  def initialize(api_key:)
    @api_key = api_key
  end

  def fetch_data
    response = HTTP.headers(Authorization: "Bearer #{@api_key}").get('https://api.vendor.com/data')
    JSON.parse(response.body)
  end
end

# In a Hanami action
class ApiController < Hanami::Action
  def call(params)
    api_key = Secrets['api.vendor.key'] # Retrieved from secure vault
    client = ApiClient.new(api_key: api_key)
    render json: client.fetch_data
  end
end

Third, sanitize any logging or error handling that might include SAML attributes or session data. Avoid printing full session or request objects to logs. If debugging is required, use structured logging that excludes sensitive fields:

Hanami.app do
  configure :production do
    logger = Logger.new(STDOUT)
    logger.formatter = proc do |severity, datetime, progname, msg|
      # Exclude sensitive keys from logs
      filtered_msg = msg.to_s.gsub(/api_key=[^&]*/, 'api_key=[FILTERED]')
      "#{datetime} #{severity} #{filtered_msg}\n"
    end
  end
end

Finally, enforce HTTPS and strict SAML validation to prevent assertion tampering. Use a trusted SAML library that verifies signatures and certificates, ensuring that attributes cannot be forged by an attacker:

# Gemfile
gem 'ruby-saml'

# In your controller
require 'onelogin/ruby-saml'

def saml_login
  settings = OneLogin::RubySaml::Settings.new(
    idp_cert_fingerprint: ENV['IDP_CERT_FIGNERPRINT'],
    issuer: 'https://idp.example.com',
    assertion_consumer_service_url: 'https://app.example.com/auth/saml/callback'
  )
  response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], settings: settings)
  if response.success?
    user = User.find_by(email: response.attributes['email'])
    # Proceed with secure session creation
  else
    halt 401, 'Invalid SAML response'
  end
end
end

Frequently Asked Questions

How can I verify that my Hanami app is not leaking API keys via SAML responses?
Use middleBrick to scan your endpoint. The tool checks for exposed keys in session data, logs, and response flows. Run: middlebrick scan https://your-hanami-app.example.com
Does the SAML attribute mapping in Hanami need to exclude API keys explicitly?
Yes. Always map only required attributes (e.g., email) and store API keys in environment-sealed vaults. Never derive keys from SAML assertions; keep them isolated using Hanami’s secure repository pattern.