HIGH cors wildcardsinatrabearer tokens

Cors Wildcard in Sinatra with Bearer Tokens

Cors Wildcard in Sinatra with Bearer Tokens — how this combination creates or exposes the vulnerability

A CORS wildcard (Access-Control-Allow-Origin: *) in Sinatra combined with Bearer token authentication creates a critical misconfiguration that can expose protected resources to unauthorized origins. When an endpoint validates tokens but also responds to any origin, a malicious site can make authenticated requests on behalf of a victim who possesses a valid token. The browser enforces CORS for cross-origin JavaScript, and a wildcard allows any domain to read the response if credentials or tokens are handled naively.

Consider a Sinatra route that checks a Bearer token but sets a permissive CORS header:

require 'sinatra'
require 'json'

before do
  # Per request CORS header, overly permissive
  headers 'Access-Control-Allow-Origin' => '*'
  headers 'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS'
  headers 'Access-Control-Allow-Headers' => 'Authorization, Content-Type'
end

get '/api/data' do
  auth = request.env['HTTP_AUTHORIZATION']
  # naive Bearer check
  if auth&& auth.start_with?('Bearer ')
    # process request — token accepted
    { secret: 'top secret', user: 'alice' }.to_json
  else
    status 401
    { error: 'Unauthorized' }.to_json
  end
end

The vulnerability arises because the wildcard origin allows a page hosted on https://evil.com to include this route via fetch or XMLHttpRequest. Even though the server validates the Bearer token, the response is delivered to the attacker’s JavaScript if the victim’s browser includes the token in an Authorization header. The wildcard signals that any origin is trusted, undermining origin-based isolation. This is especially dangerous for token-based APIs where the token is stored in browser-accessible JavaScript or where tokens are passed in headers from a compromised frontend.

In the context of API security scanning, this issue maps to BOLA/IDOR and Property Authorization checks. A scanner can detect the combination of permissive CORS and bearer-based authentication by cross-referencing the OpenAPI spec’s security schemes with the runtime CORS headers. A spec defining Bearer authentication but missing strict Access-Control-Allow-Origin controls will be flagged with high severity, as it enables unauthorized data access via browser-based scripts.

Additional risk occurs during preflight requests. If the server responds to OPTIONS with a wildcard origin and allows credentials-related headers without validating the origin, an attacker can craft a two-stage exploit: first, probe allowed methods and headers, then perform authenticated requests using the victim’s token. This pattern is consistent with CORS misconfigurations observed in real-world API breaches, where token validation is present but origin policy is unrestricted.

Bearer Tokens-Specific Remediation in Sinatra — concrete code fixes

Remediation focuses on tightening CORS policy and ensuring token checks remain authoritative without relying on permissive origins. Replace the wildcard with explicit origins and consider dynamic reflection only when necessary. Always pair CORS with proper authentication checks and avoid exposing sensitive data to untrusted origins.

1) Restrict origins instead of using a wildcard

require 'sinatra'
require 'json'

configure do
  # Define allowed origins explicitly or via environment
  set :allowed_origins, ['https://app.yourdomain.com', 'https://admin.yourdomain.com']
end

before do
  origin = request.env['HTTP_ORIGIN']
  allowed = settings.allowed_origins
  if allowed.include?(origin)
    headers 'Access-Control-Allow-Origin' => origin
    headers 'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS'
    headers 'Access-Control-Allow-Headers' => 'Authorization, Content-Type'
    headers 'Access-Control-Allow-Credentials' => 'true' if request.options?
  end

  if request.options?
    # Preflight response
    headers 'Access-Control-Max-Age' => '86400'
    halt 200
  end
end

get '/api/data' do
  auth = request.env['HTTP_AUTHORIZATION']
  halt 401, { error: 'Unauthorized' }.to_json unless auth&& auth.start_with?('Bearer ')
  # Validate token against your auth provider here
  { secret: 'top secret', user: 'alice' }.to_json
end

By explicitly listing origins, you ensure only trusted frontends can read responses. The server reflects the requesting origin only when it matches an allowed entry, preventing arbitrary origins from receiving authenticated data.

2) Avoid credentials and wildcard together, and validate tokens rigorously

before do
  origin = request.env['HTTP_ORIGIN']
  allowed = settings.allowed_origins
  if allowed.include?(origin)
    headers 'Access-Control-Allow-Origin' => origin
    headers 'Access-Control-Allow-Credentials' => 'true'
    headers 'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS'
    headers 'Access-Control-Allow-Headers' => 'Authorization, Content-Type'
  end
  # Preflight handling as above
end

helpers do
  def authenticate!
    auth = request.env['HTTP_AUTHORIZATION']
    halt 401, { error: 'Unauthorized' }.to_json unless auth&& auth.match?(/\ABeer\S+\s+(\S+)\z/)
    token = $1
    # Perform token validation — e.g., verify signature, scope, expiry
    # For illustration, accept a specific test token
    halt 403, { error: 'Forbidden' }.to_json unless token == 'valid_token_123'
  end
end

get '/api/secure' do
  authenticate!
  { data: 'protected resource' }.to_json
end

This approach removes the wildcard, adds explicit origin checks, and keeps token validation separate from CORS logic. It aligns with the principle of least privilege: origins are whitelisted, credentials are only sent to trusted sources, and tokens are validated before any data is returned.

In practice, combine this with an OpenAPI spec that declares the Bearer security scheme and documents allowed origins. MiddleBrick’s scanning can highlight the mismatch between a strict security scheme and a permissive CORS policy, guiding you toward compliant configurations.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Does setting Access-Control-Allow-Origin to * always break Bearer token security?
It creates a high risk when endpoints validate tokens but accept requests from any origin. A wildcard allows malicious pages to make authenticated requests if the victim’s browser includes the token. Use explicit origin lists instead.
Should I include credentials when using a wildcard CORS policy?
Never use Access-Control-Allow-Credentials: true with a wildcard origin. Browsers reject such combinations for security. Define specific origins when credentials are required.