Log Injection in Express with Api Keys
Log Injection in Express with Api Keys — how this specific combination creates or exposes the vulnerability
Log injection occurs when untrusted input is written directly into application logs without proper sanitization or formatting. In Express applications that rely on API keys for authentication or rate limiting, the combination of key usage patterns and insufficient log hygiene can turn logs into an unintended attack surface. API keys often appear in HTTP headers such as x-api-key, and if these values are logged verbatim, an attacker can manipulate them to inject newline characters or structured log fragments.
Consider an Express route that authenticates requests by checking x-api-key and logs the key for debugging:
const express = require('express');
const app = express();
app.use((req, res, next) => {
const apiKey = req.header('x-api-key');
if (apiKey) {
console.log(`[Auth] API key received: ${apiKey}`);
}
next();
});
app.get('/data', (req, res) => {
res.json({ message: 'ok' });
});
app.listen(3000);
If an attacker sends a request with x-api-key: abc123\n[SYSTEM] admin=true, the log line becomes two logical entries in one line, potentially obscuring the boundary between user data and system metadata. This can interfere with log-based monitoring, enable log forging to hide malicious activity, or facilitate log injection that supports further attacks such as log poisoning or log forging referenced in the OWASP API Security Top 10.
Log injection with API keys is not strictly an authentication bypass, but it weakens auditability and can be chained with other weaknesses. For example, an attacker might inject crafted log lines that, when viewed in a log aggregation UI that interprets newline or structured separators, appear as separate events. This can complicate incident response and violate expected observability semantics. The risk is elevated when logs contain sensitive fragments such as keys themselves, because log retention policies may inadvertently expose credentials, increasing the impact of a later log access compromise.
In a middleBrick scan, such issues are surfaced under the Unsafe Consumption and Data Exposure checks, with remediation guidance focused on input validation and structured logging. The scanner does not alter logs or block requests; it highlights where attacker-controlled data reaches log output and provides prioritized findings mapped to relevant frameworks, including specific references to authentication and authorization checks.
Api Keys-Specific Remediation in Express — concrete code fixes
Remediation centers on ensuring that API key values are never written directly into logs and that any data written to logs is sanitized and structured. The safest approach is to avoid logging raw keys entirely. Instead, log a hashed or truncated representation, and ensure that log lines cannot be composed into multiple logical records by an attacker.
Example: hash the key before logging and avoid interpolating untrusted strings into log messages:
const express = require('express');
const crypto = require('crypto');
const app = express();
function hashKey(key) {
return crypto.createHash('sha256').update(key).digest('hex');
}
app.use((req, res, next) => {
const apiKey = req.header('x-api-key');
if (apiKey) {
console.log(`[Auth] API key hash: ${hashKey(apiKey)}`);
}
next();
});
app.get('/data', (req, res) => {
res.json({ message: 'ok' });
});
app.listen(3000);
If you must retain partial key visibility for operational debugging, truncate and sanitize:
function safeKeyFragment(key, length = 6) {
if (!key) return 'none';
return key.slice(0, length);
}
app.use((req, res, next) => {
const apiKey = req.header('x-api-key');
if (apiKey) {
console.log(`[Auth] API key fragment: ${safeKeyFragment(apiKey)}`);
}
next();
});
Additionally, enforce strict input validation for the API key header to reduce the attack surface. Reject keys containing unexpected characters or newline sequences:
app.use((req, res, next) => {
const apiKey = req.header('x-api-key');
if (apiKey && /^[A-Za-z0-9\-_]+$/.test(apiKey)) {
// Proceed with authentication logic
} else {
return res.status(400).json({ error: 'invalid_api_key' });
}
next();
});
For production-grade protection, combine these practices with centralized log management that supports structured logging (e.g., JSON) so that fields are not concatenated in a way that enables injection. middleBrick’s scans highlight these patterns and provide prioritized remediation steps, helping you align with secure logging guidance without requiring changes to your authentication flow.