HIGH dangling dnsgrapebearer tokens

Dangling Dns in Grape with Bearer Tokens

Dangling Dns in Grape with Bearer Tokens — how this specific combination creates or exposes the vulnerability

A dangling DNS record occurs when a hostname (e.g., auth.example.internal) resolves to an IP that no longer hosts the intended service. In Grape, a Ruby API framework, this situation becomes high risk when Bearer tokens are used for authentication but token validation depends on external resources that can become dangling. For example, if your app validates tokens by introspecting an authorization server discovered via DNS, and that DNS entry points to a decommissioned or reassigned host, the validation path may be redirected or time out in unpredictable ways.

Consider an API that uses a JWT with a kid header to locate a public key. The key URI is obtained from a well-known JWKS endpoint whose hostname is resolved via DNS. If the DNS record for that endpoint is dangling—pointing to an inactive or repurposed server—the app may fetch keys from an unexpected source, accept invalid signatures, or fail open depending on error handling. This is especially dangerous when Bearer tokens are accepted without strict hostname pinning, enabling token validation against a rogue or unverified key. The combination of a dangling DNS record and Bearer token flows can lead to authorization bypass, token substitution, or unauthenticated access when the app trusts a misresolved endpoint.

In a black-box scan, middleBrick tests for such scenarios by probing authentication and token validation paths while correlating findings with the API specification. For instance, an OpenAPI definition with a security scheme of type http and a bearer format may reference an authorization URL whose host resolves inconsistently. If runtime checks show the host resolves to an unexpected IP or the TLS certificate does not match the expected identity, middleBrick flags this as a high-severity finding under Authentication and BOLA/IDOR checks. The scanner also tests input validation and rate limiting to ensure malformed or repeated token requests do not leak information or allow brute-force attempts against dangling endpoints.

Additionally, middleBrick’s LLM/AI Security checks are relevant when token introspection or key retrieval involves LLM-driven workflows. A dangling DNS record could cause an LLM-integrated service to fetch keys or policies from an unintended source, risking prompt injection or data exfiltration if the model is tricked into using a compromised endpoint. By aligning spec-defined Bearer token usage with runtime resolution behavior, middleBrick ensures that security findings are actionable and mapped to frameworks like OWASP API Top 10 and SOC2.

Bearer Tokens-Specific Remediation in Grape — concrete code fixes

To remediate risks related to Bearer tokens and dangling DNS in Grape, focus on hardening token validation, avoiding reliance on dynamic external discovery at runtime, and ensuring strict host and certificate verification. Below are concrete code examples using the grape gem and common libraries such as jwt and net-http.

1. Use static JWKS URI and enforce hostname verification

Instead of resolving a hostname via DNS at runtime, pin the JWKS endpoint to a specific IP or hostname and verify the TLS certificate. This prevents redirection to a dangling or malicious host.

require 'grape'
require 'jwt'
require 'net/http'
require 'openssl'

class AuthValidator
  JWKS_URI = 'https://auth.example.com/.well-known/jwks.json'.freeze
  EXPECTED_HOST = 'auth.example.com'

  def self.call!(req)
    token = req.headers['Authorization']&.to_s&.sub(/^Bearer\s+/, '')
    return { error: 'Missing token' }, 401 unless token

    # Fetch with pinned host and strict SSL
    uri = URI(JWKS_URI)
    raise 'Host mismatch' unless uri.host == EXPECTED_HOST

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    # Optionally set ssl_params to pin certificate or public key

    request = Net::HTTP::Get.new(uri)
    response = http.request(request)
    raise 'Failed to fetch JWKS' unless response.is_a?(Net::HTTPSuccess)

    jwks = JSON.parse(response.body)
    key = jwks['keys'].find { |k| k['kid'] == token_header_kid(token) }&.then { |k| JWT::JWK.import(k) }
    raise 'Key not found' unless key

    decoded = JWT.decode(token, key, true, { algorithm: 'RS256' })
    { user: decoded.first['sub'] }
  rescue => e
    { error: e.message }, 401
  end

  def self.token_header_kid(token)
    # Decode header without verification to extract kid
    header = JWT.decode(token, nil, false).first
    header['kid']
  end
end

class MyAPI < Grape::API
  before { AuthValidator.call!(request) }
  # ... your endpoints
end

2. Avoid dynamic host resolution for token introspection

If your API relies on an OAuth introspection endpoint, avoid looking up the host via DNS on each request. Instead, configure the endpoint URL statically and validate the server’s certificate against a trusted CA or public key pinning.

INTROSPECTION_URL = 'https://introspect.example.com/oauth/introspect'.freeze

def introspect_token(token)
  uri = URI(INTROSPECTION_URL)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER

  req = Net::HTTP::Post.new(uri)
  req['Authorization'] = 'Basic ' + Base64.strict_encode64("client_id:client_secret")
  req['Content-Type'] = 'application/x-www-form-urlencoded'
  req.body = { token: token }
  res = http.request(req)
  JSON.parse(res.body)
end

3. Validate token audience and issuer strictly

Ensure that your Bearer token validation checks iss (issuer) and aud (audience) against expected values, and reject tokens with missing or mismatched claims. This reduces the impact if a token is mistakenly accepted due to a DNS or configuration error.

expected_issuer = 'https://auth.example.com'
expected_audience = 'my-api'

decoded = JWT.decode(token, key, true, {
  algorithm: 'RS256',
  iss: expected_issuer,
  verify_iss: true,
  aud: expected_audience,
  verify_aud: true
})

4. Use middleware for consistent Bearer token handling

Encapsulate token validation in a reusable middleware or helper to ensure all endpoints apply the same strict checks. middleBrick’s scans can then verify that authentication is consistently enforced across the API surface.

class BearerAuth
  def initialize(app)
    @app = app
  end

  def call(env)
    req = Rack::Request.new(env)
    token = req.get_header('HTTP_AUTHORIZATION')&.to_s&.sub(/^Bearer\s+/, '')
    if token && valid_token?(token)
      @app.call(env)
    else
      [401, { 'Content-Type' => 'application/json' }, [{ error: 'Unauthorized' }.to_json]]
    end
  end

  def valid_token?(token)
    # implement validation logic here
  end
end

# In your Grape app
use BearerAuth

5. Monitor and rotate secrets and certificates

Ensure that keys, certificates, and client secrets are rotated regularly. Automate renewal and deployment to avoid long-lived credentials that could be exposed if a DNS record becomes dangling during rotation.

For teams using middleBrick, the Pro plan supports continuous monitoring and GitHub Action integration to fail builds if authentication checks regress. This helps catch misconfigurations—such as a dangling DNS record affecting token validation—before they reach production.

Frequently Asked Questions

How does middleBrick detect issues related to Bearer tokens and dangling DNS?
middleBrick runs parallel security checks including Authentication and BOLA/IDOR. It probes token validation paths, inspects OpenAPI spec references to authorization servers, and tests runtime resolution to identify mismatches or reliance on dynamic discovery that can be disrupted by dangling DNS records.
Can middleBrick’s LLM/AI Security checks help identify risks when token flows involve AI components?
Yes. middleBrick’s LLM/AI Security checks detect system prompt leakage, active prompt injection attempts, and output scanning for exposed credentials. If Bearer token flows or key retrieval are influenced by LLM-driven logic, these checks help identify unsafe patterns and unintended data exposure.