Cors Wildcard in Sinatra with Hmac Signatures
Cors Wildcard in Sinatra with Hmac Signatures — how this specific combination creates or exposes the vulnerability
A CORS wildcard (Access-Control-Allow-Origin: *) combined with HMAC signatures in Sinatra can unintentionally expose authenticated or sensitive endpoints to any origin. In Sinatra, if responses include both a wildcard CORS header and signature-based authorization, the signature may be leaked to untrusted origins via response inspection or cross-origin reads, undermining the purpose of the signature.
HMAC signatures in this context are typically used to ensure request integrity and authenticity, for example by signing a request’s method, path, timestamp, and body. A server-side Sinatra route might compute an HMAC over these components and require the client to present the signature in a header such as x-api-signature. If the route also sets Access-Control-Allow-Origin: *, browsers allow JavaScript from any origin to read the response, including any data returned alongside or derived from the signature logic (e.g., via timing differences or error messages).
Consider a Sinatra endpoint that verifies an HMAC and then returns user-specific data. With a wildcard CORS policy, any site can make a request and read the response. While CORS alone does not allow cross-origin requests to bypass server-side authorization, it can facilitate information leakage when combined with misconfigured origins and signature-based flows. For instance, an attacker’s page can issue requests that include valid HMAC signatures (if signing keys or nonces are mishandled), or trick a victim’s browser into sending authenticated requests where the wildcard origin allows exfiltration of data via the attacker’s script.
Real-world attack patterns mirror issues cataloged in the OWASP API Top 10, particularly broken object level authorization (BOLA) and improper restrictions on cross-origin resource sharing. The combination is also relevant to CWE-942 (Improper Restriction of Excessive Authentication Attempts) when signatures are leaked, and can amplify risks around data exposure and SSRF if the endpoint internally uses the origin or signature data in unsafe ways.
In practice, this risk emerges when developers assume HMAC signatures alone protect endpoints while allowing any origin to read responses. The correct posture is to restrict Access-Control-Allow-Origin to known, trusted origins and to avoid reflecting or exposing any secret-derived material in responses that a wildcard would permit. middleBrick detects such dangerous combinations under its CORS, Authentication, and Data Exposure checks, providing prioritized findings with remediation guidance.
Hmac Signatures-Specific Remediation in Sinatra — concrete code fixes
To remediate the risk, you should ensure CORS is restricted and HMAC verification is strict. Use a whitelist of origins instead of a wildcard, and validate the signature before processing any sensitive logic. Below are concrete Sinatra examples showing a vulnerable configuration and a secure fix.
Vulnerable example: wildcard CORS and naive HMAC check
require 'sinatra'
require 'openssl'
require 'json'
set :bind, '0.0.0.0'
helpers do
def valid_signature?(request)
secret = ENV['HMAC_SECRET']
payload = request.body.read
request.body.rewind
signature = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
Rack::Utils.secure_compare(signature, request.env['HTTP_X_API_SIGNATURE'] || '')
end
end
# Vulnerable: wildcard CORS and signature check after potential data exposure
post '/data' do
content_type :json
# Vulnerable: CORS wildcard allows any origin to read this response
headers 'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type,x-api-signature'
if request.options?
# preflight
halt 200
end
unless valid_signature?(request)
halt 401, { error: 'invalid signature' }.to_json
end
# Process sensitive data
{ status: 'ok', data: 'sensitive' }.to_json
end
Secure remediation: strict origins and early validation
require 'sinatra'
require 'openssl'
require 'json'
set :bind, '0.0.0.0'
helpers do
def valid_signature?(request)
secret = ENV['HMAC_SECRET']
payload = request.body.read
request.body.rewind
signature = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
Rack::Utils.secure_compare(signature, request.env['HTTP_X_API_SIGNATURE'] || '')
end
def allowed_origin?(origin)
# Whitelist trusted origins; avoid wildcards
trusted = ENV.fetch('TRUSTED_ORIGINS', '').split(',').map(&:strip)
trusted.include?(origin)
end
end
# Secure: explicit origin control and early HMAC validation
before do
origin = request.env['HTTP_ORIGIN']
if origin && allowed_origin?(origin)
headers 'Access-Control-Allow-Origin' => origin,
'Access-Control-Allow-Methods' => 'POST, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type,x-api-signature'
end
if request.options?
halt 200
end
unless valid_signature?(request)
halt 401, { error: 'invalid signature' }.to_json
end
end
post '/data' do
content_type :json
# Only trusted origins that passed the before filter can read this
{ status: 'ok', data: 'sensitive' }.to_json
end
Additional recommendations
- Never use
Access-Control-Allow-Origin: *when responses include authentication- or signature-derived information. - Validate the signature before reading the request body in ways that could leak information; avoid branching on signature validity in a way that produces different timing or error paths.
- Use
Rack::Utils.secure_comparefor signature comparison to prevent timing attacks. - Consider adding per-request nonces or timestamps and enforce short validity windows to reduce replay risk.
- In production, combine these checks with CSP and tight network policies; middleBrick’s continuous monitoring can alert you if CORS or authentication findings reappear after changes.
By pairing strict CORS policies with robust HMAC verification, you reduce the attack surface for cross-origin abuse and keep signature-based integrity controls effective.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |
Frequently Asked Questions
Why is using a CORS wildcard dangerous when HMAC signatures are in place?
How can I securely configure CORS in Sinatra while using HMAC signatures?
Access-Control-Allow-Origin to specific trusted origins, validate the HMAC before processing sensitive logic, use Rack::Utils.secure_compare for comparisons, and avoid reflecting secrets or signature material in responses.