HIGH header injectionexpressapi keys

Header Injection in Express with Api Keys

Header Injection in Express with Api Keys — how this specific combination creates or exposes the vulnerability

Header Injection in an Express API that uses API keys occurs when user-controlled data is reflected into HTTP response headers without validation or sanitization. An attacker can supply newline characters (e.g., %0D%0A or literal \r\n) within a header value, causing the server to inject additional headers. This can lead to HTTP response splitting, cache poisoning, or the injection of security-sensitive headers that override intended behavior.

When API keys are passed via request headers (e.g., x-api-key), and the server includes key-derived values or echo user input into other headers, the risk increases. For example, if you log or reflect the API key in a custom header such as x-client-key without sanitization, an attacker can inject extra headers like Set-Cookie or Location, potentially bypassing intended routing or authentication logic. Even when API keys are validated, a vulnerable pattern that concatenates or echoes key material into headers can expose internal routing details or aid in SSRF-assisted attacks by injecting malicious forward paths.

Express does not sanitize headers automatically. If your code does something like res.set('x-api-key', userSuppliedKey) where userSuppliedKey originates from an external source (query, header, or body), newline characters enable multi-line header injection. This pairs poorly with API key usage because keys are often logged or echoed for debugging, increasing visibility to attackers. The unauthenticated scan checks for such unsafe reflection patterns and flags them as data exposure or input validation failures, noting risks like response manipulation or information leakage.

In the context of the 12 security checks, header injection intersects with Input Validation and Data Exposure. Unsafe reflection of API keys or related identifiers into headers can reveal internal structures or aid in smuggling attacks. Injection can also compound issues like BOLA/IDOR if manipulated headers influence resource access logic. Because API keys often act as authorization tokens, exposing or weakening their handling through header injection undermines integrity even when the key itself remains secret.

Api Keys-Specific Remediation in Express — concrete code fixes

Remediation focuses on strict validation, avoiding reflection of untrusted input into headers, and using safe patterns for API key handling in Express. Never directly set response headers with values derived from client input. If you must pass keys or identifiers, keep them server-side and avoid echoing them to the client or into other headers.

Safe approach: validate the API key, store server-side metadata separately, and do not reflect user input into headers. Below are two examples — one vulnerable and one remediated.

Vulnerable pattern (do not use)

const express = require('express');
const app = express();

app.use((req, res, next) => {
  const apiKey = req.headers['x-api-key'];
  // Vulnerable: echoing user-controlled API key into another header
  if (apiKey) {
    res.set('x-client-key', apiKey); // Risk: header injection if apiKey contains \r\n
  }
  next();
});

app.get('/resource', (req, res) => {
  res.json({ data: 'example' });
});

app.listen(3000);

In the vulnerable example, if an attacker sends x-api-key: abc\r\nSet-Cookie: session=evil, Express may add an extra Set-Cookie header, enabling session fixation or cache poisoning.

Remediated pattern (use this)

const express = require('express');
const app = express();

// Validate API key format (alphanumeric + limited length) before any use
function isValidApiKey(key) {
  return typeof key === 'string' && /^[A-Za-z0-9\-_]{8,64}$/.test(key);
}

app.use((req, res, next) => {
  const apiKey = req.headers['x-api-key'];
  if (apiKey && isValidApiKey(apiKey)) {
    // Safe: keep key usage server-side; do not reflect into headers
    req.apiKey = apiKey; // store for internal authz checks
    // Do NOT set headers with user-controlled key material
  } else {
    // Reject invalid keys early with 400 to avoid processing
    return res.status(400).json({ error: 'Invalid API key' });
  }
  next();
});

app.get('/resource', (req, res) => {
  // Perform authorization using server-side stored req.apiKey
  res.json({ data: 'secure-data' });
});

app.listen(3000);

The remediated pattern validates the API key format, avoids reflecting it into response headers, and keeps key usage server-side. This prevents newline-based injection and reduces information leakage. If you use the middleBrick CLI (middlebrick scan <url>) or GitHub Action, such patterns will align with input validation and data exposure checks, and findings will map to frameworks like OWASP API Top 10 and PCI-DSS.

Additional recommendations: enforce strict Content-Type and CORS policies, avoid logging raw API keys, and rotate keys via your management workflow. For advanced workflows requiring key introspection, keep metadata on the server and reference by a non-sensitive token instead of echoing the key.

Frequently Asked Questions

Can header injection bypass API key validation in Express?
Yes, if API key validation logic is influenced by injected headers (e.g., via host or forwarded headers), an attacker may bypass intended checks. Always parse and validate keys independently and avoid using potentially injected headers for access decisions.
Does middleBrick detect header injection with API keys in Express?
Yes. The scanner includes input validation and data exposure checks that identify unsafe reflection of keys into headers. Findings include severity, location, and remediation guidance, and results can be tracked in the dashboard or integrated via the GitHub Action.