HIGH rate limiting bypassexpressapi keys

Rate Limiting Bypass in Express with Api Keys

Rate Limiting Bypass in Express with Api Keys — how this specific combination creates or exposes the vulnerability

In Express applications, using API keys alone does not enforce rate limits and can create a bypass scenario when rate limiting is not applied uniformly or is tied to an identity that can be abused. A common pattern is to read the API key from headers, query parameters, or a bearer token, then allow the request to proceed without a per-key or per-client limit. If middleware that enforces rate limits is configured to skip counting when an API key is missing or invalid, an attacker who discovers or guesses a valid key can exhaust the quota for that key while other identifiers (such as IP) may still be rate-limited separately.

Consider an Express route that checks for an API key but does not incorporate the key into the rate-limiting bucket:

const rateLimit = require('express-rate-limit');
const ApiKeyValidator = require('./apiKeyValidator'); // custom module

const limiter = rateLimit({
  windowMs: 60 * 1000,
  max: 100,
  keyGenerator: (req) => req.ip, // rate limit by IP only
  skip: (req) => !ApiKeyValidator.hasKey(req) // skip if no key
});

app.use('/api/v1/data', limiter, (req, res) => {
  const key = req.headers['x-api-key'];
  if (!ApiKeyValidator.isValidKey(key)) {
    return res.status(401).json({ error: 'Invalid API key' });
  }
  res.json({ data: 'sensitive data' });
});

In this setup, if an attacker obtains a valid API key, they can send up to 100 requests per minute under that key while the limiter still counts requests by IP. Because the limiter skips when the key is missing, the attacker can rotate among multiple stolen keys or reuse a single key to effectively bypass intended per-client throttling. The key is treated as an authorization check rather than a rate-limiting identifier, creating a mismatch between authentication and rate control.

Another bypass pattern involves middleware ordering. If API key validation is performed after the rate limiter, the limiter may apply to unauthenticated requests (without a key), while authenticated requests with a valid key may be subject to a higher limit or no limit at all if the limiter is scoped incorrectly. For example:

app.use('/api/v1/admin', apiKeyCheck, adminLimiter); // adminLimiter may be lenient or missing
app.use('/api/v1/public', publicLimiter);

If adminLimiter is not configured with a strict max and windowMs, or if it uses a broader key generator that does not incorporate the API key, an attacker who authenticates as an admin client can drive higher throughput. The presence of an API key should tighten controls, not relax them, and the rate limiter must include the key in its identifier to ensure per-key quotas are enforced consistently.

SSRF and external probing can also reveal whether rate limiting is key-aware. By sending requests with and without keys, an attacker can infer whether the server applies different limits based on authentication state. This can be part of automated reconnaissance during an unauthenticated scan, where endpoints that expose different behavior depending on key presence indicate a potential bypass.

Api Keys-Specific Remediation in Express — concrete code fixes

To prevent rate limiting bypass when using API keys, tie the rate limiter to the API key itself and ensure validation and throttling happen within the same logical flow. The key should be treated as part of the rate-limiting identity, and the middleware should not skip counting for authenticated requests.

Use a key-aware limiter configuration that includes the API key in the keyGenerator. If the key is present but invalid, reject the request before the limiter to avoid leaking information about valid keys through timing differences. Here is a secure pattern:

const rateLimit = require('express-rate-limit');

const apiKeyLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 100,
  keyGenerator: (req) => {
    // Prefer header, fall back to query for compatibility
    return req.headers['x-api-key'] || req.query.api_key;
  },
  skip: (req) => {
    // Do not skip if key is missing; handle missing key later to keep behavior consistent
    return false;
  }
});

app.use('/api/v1/data', apiKeyLimiter, (req, res, next) => {
  const key = req.headers['x-api-key'] || req.query.api_key;
  if (!ApiKeyValidator.isValidKey(key)) {
    return res.status(401).json({ error: 'Invalid or missing API key' });
  }
  next();
});

app.use('/api/v1/data', (req, res) => {
  res.json({ data: 'rate-limited and authenticated data' });
});

In this configuration, the rate limiter counts requests per API key, ensuring that a compromised key cannot be used to exceed per-key quotas. By keeping the validation after the limiter’s identifier extraction but before business logic, you maintain consistent behavior and avoid signaling the presence of valid keys through different response paths.

For multi-tenant or shared-key scenarios, use namespaced keys or key prefixes to isolate clients and enforce organization-level limits. Rotate keys regularly and monitor usage via logs to detect spikes that may indicate abuse or accidental exhaustion.

If you use a dedicated security or API management layer, ensure its rate-limiting rules mirror the same key scope as your Express middleware. Misalignment between gateway limits and application-level limits can still allow bypasses. The CLI tool (middlebrick scan <url>) can detect inconsistencies between authentication and rate limiting in unauthenticated scans, and the GitHub Action can enforce a minimum security score in CI/CD pipelines to catch regressions before deployment.

When adopting continuous monitoring (Pro plan), configure alerts for abnormal request volumes tied to specific API keys. Dashboard tracks score changes over time and can surface findings related to authentication and rate limiting, helping you maintain a robust posture without relying on manual audits.

Related CWEs: resourceConsumption

CWE IDNameSeverity
CWE-400Uncontrolled Resource Consumption HIGH
CWE-770Allocation of Resources Without Limits MEDIUM
CWE-799Improper Control of Interaction Frequency MEDIUM
CWE-835Infinite Loop HIGH
CWE-1050Excessive Platform Resource Consumption MEDIUM

Frequently Asked Questions

Can an attacker bypass rate limits if API keys are exposed in client-side code?
Yes. If API keys are embedded in client-side JavaScript, they can be extracted and reused to drive requests past server-side rate limits. Mitigate by keeping keys server-side, using short-lived tokens, and enforcing per-key quotas in Express middleware.
Does middleBrick detect rate limiting bypass via API key misconfiguration?
middleBrick performs unauthenticated scans and tests whether rate limiting varies by key presence. Findings include severity, remediation guidance, and mapping to frameworks such as OWASP API Top 10 to help prioritize fixes.