Api Key Exposure with Bearer Tokens
How Api Key Exposure Manifests in Bearer Tokens
Bearer token exposure occurs when API keys or secrets are inadvertently leaked through HTTP headers, logs, or error messages. In Bearer token authentication, the token is sent as an Authorization header: Authorization: Bearer . This creates multiple exposure vectors:
- HTTP Headers in Logs: Web servers, reverse proxies, and middleware often log all request headers by default. If logging is not configured to exclude Authorization headers, tokens appear in plaintext in log files.
- Stack Traces: When authentication fails, some frameworks include the full Authorization header in error messages or stack traces returned to clients.
- Client-Side Exposure: Single-page applications that store tokens in localStorage or sessionStorage can expose them to XSS attacks. Tokens in cookies with
httpOnlyset to false are accessible via JavaScript. - Referrers: If an API endpoint is accessed from a web page, the full URL including query parameters (if tokens are passed there) can be sent in the Referer header to external sites.
A concrete example: a Node.js Express app using middleware that logs all headers:
app.use((req, res, next) => {
console.log(`Request from ${req.ip}: ${req.method} ${req.url}`);
console.log('Headers:', req.headers); // Logs Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
next();
});
This logs the complete Bearer token to stdout, where it might be captured by log aggregation services or monitoring tools. Another common pattern is error responses that echo back the Authorization header:
app.get('/api/protected', (req, res) => {
if (!req.headers.authorization) {
return res.status(401).json({
error: 'Missing token',
authHeader: req.headers.authorization // Returns null, but could expose if present
});
}
});
Even though this returns null, a malformed request could cause the server to include the header value in error messages or debugging output.
Bearer Tokens-Specific Detection
Detecting API key exposure in Bearer token implementations requires examining multiple layers of the request-response cycle. The most effective approach combines automated scanning with manual code review.
Automated Scanning with middleBrick: The middleBrick scanner tests for Authorization header exposure by making requests to API endpoints and analyzing responses. It checks for:
- Tokens appearing in HTTP response bodies (error messages, stack traces)
- Tokens in response headers (Server timing, X-Debug headers)
- Tokens in redirect URLs or Location headers
- Tokens in publicly accessible documentation or OpenAPI specs
middleBrick's black-box scanning approach sends test requests and analyzes the unauthenticated attack surface without requiring credentials. For Bearer tokens specifically, it looks for patterns like:
Authorization: Bearer
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
appearing in responses where they shouldn't be present.
Manual Detection Checklist:
| Detection Area | What to Check | Tools/Methods |
|---|---|---|
| Log Files | d>Search for Authorization headers in server logsgrep, log analysis tools | |
| Error Responses | d>Check if auth headers appear in 401/403 responsesManual testing, automated scanners | |
| OpenAPI Specs | d>Verify tokens aren't hardcoded in documentationmiddleBrick spec analysis | |
| Client Storage | d>Check if tokens stored in localStorage/cookiesBrowser dev tools, security scanners |
Network Traffic Analysis: Using tools like Wireshark or browser dev tools to capture requests and verify that Authorization headers are not being logged or transmitted insecurely. Pay special attention to:
- Middleware that logs all request data
- Reverse proxies with verbose logging
- Debug endpoints that echo request data
Bearer Tokens-Specific Remediation
Remediating API key exposure in Bearer token systems requires a multi-layered approach addressing both code and infrastructure.
Code-Level Fixes:
// 1. Configure logging to exclude sensitive headers
const express = require('express');
const app = express();
// Custom logger that redacts Authorization header
const redactLogger = (req, res, next) => {
const { authorization, ...safeHeaders } = req.headers;
console.log(`Request: ${req.method} ${req.url}`, safeHeaders);
next();
};
app.use(redactLogger);
// 2. Sanitize error responses
app.get('/api/protected', (req, res, next) => {
try {
if (!req.headers.authorization) {
throw new Error('Authentication required');
}
// Verify token...
next();
} catch (error) {
console.error('Auth error:', error.message); // Don't log error.stack if it contains headers
res.status(401).json({ error: 'Authentication failed' });
}
});
// 3. Use httpOnly cookies for browser clients
app.use((req, res, next) => {
res.cookie('auth_token', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
next();
});
Infrastructure-Level Controls:
- Log Redaction: Configure logging frameworks to automatically redact Authorization headers. In Node.js Winston, use a custom format:
const { createLogger, format, transports } = require('winston');
const redactAuth = format((info, opts) => {
if (info.req) {
const { authorization, ...headers } = info.req.headers;
info.req.sanitizedHeaders = headers;
}
return info;
});
const logger = createLogger({
format: format.combine(
redactAuth(),
format.json()
),
transports: [new transports.Console()]
});
Security Headers and Controls:
// Prevent token exposure via referrer
app.use((req, res, next) => {
res.setHeader('Referrer-Policy', 'no-referrer');
next();
});
// Content Security Policy to prevent token theft via XSS
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self' 'nonce-...';");
next();
});
Testing the Fix: After implementing remediation, use middleBrick to verify that tokens no longer appear in responses. The scanner should show improved scores in the Authentication and Data Exposure categories.