HIGH api rate abuserestifymutual tls

Api Rate Abuse in Restify with Mutual Tls

Api Rate Abuse in Restify with Mutual Tls — how this specific combination creates or exposes the vulnerability

Rate abuse in Restify when mutual TLS (mTLS) is used centers on how authentication and authorization boundaries interact with per-client request volume. With mTLS, the server validates client certificates during the TLS handshake, establishing identity before HTTP traffic begins. This can create a false sense of security: operators assume mTLS alone prevents abuse, but rate limiting must still be enforced at the application layer to control how frequently a particular certificate identity can make requests.

In this setup, each client presents a certificate; if the server maps the certificate to an API key, user ID, or organizational tenant, attackers can still exploit endpoints that lack explicit rate limits. For example, an authenticated endpoint like /api/v1/transactions may allow unlimited requests from a valid mTLS client, enabling credential stuffing, scraping, or resource exhaustion. Attackers may also rotate through multiple stolen or compromised certificates to bypass per-client limits if the server does not also enforce aggregate or global caps.

The interaction with unauthenticated attack surface scanning is important: middleBrick tests endpoints without credentials and flags missing rate controls. Even with mTLS, if a route does not validate request frequency, the scan will surface findings such as missing rate limiting or weak throttling policies. Specific attack patterns enabled by this combination include rapid repeated calls that exhaust connection pools, trigger downstream backpressure, or amplify costs in metered services. Because mTLS ensures identity, abuse can be targeted at specific tenants, making detection via per-client analytics essential.

Consider a scenario where a Restify server uses tls.createServer with requestCert: true and rejectUnauthorized: true. The server may authenticate the certificate and extract a username via a custom field in the cert, but if no middleware enforces a token bucket or leaky bucket limit per username, the route remains vulnerable. Attackers who obtain valid certificates can issue high-volume, low-and-slow requests that evade IP-based defenses, highlighting the need for explicit rate limit checks tied to the authenticated identity supplied by mTLS.

middleBrick scans such APIs using unauthenticated probes and per-category checks, including Rate Limiting and Authentication. Findings highlight whether rate limiting is present, whether it applies per authenticated identity, and whether global caps exist. Remediation guidance focuses on binding rate limits to the mTLS-authenticated subject and ensuring consistent enforcement across routes.

Mutual Tls-Specific Remediation in Restify — concrete code fixes

To mitigate rate abuse with mTLS in Restify, enforce rate limits after successful certificate authentication, keyed by a stable identifier extracted from the client certificate. Combine per-identity limits with global caps to prevent both targeted and aggregate abuse. Below are concrete, syntactically correct examples that show how to implement this pattern.

Basic mTLS setup with rate limiting per certificate subject

const tls = require('tls');
const fs = require('fs');
const restify = require('restify');

const app = restify.createServer({
  tlsOptions: {
    key: fs.readFileSync('server-key.pem'),
    cert: fs.readFileSync('server-cert.pem'),
    ca: [fs.readFileSync('ca-cert.pem')],
    requestCert: true,
    rejectUnauthorized: true,
  },
});

// Simple in-memory rate limiter: { subject -> { count, last } }
const limits = new Map();
const RATE = 30; // requests
const WINDOW = 60 * 1000; // 1 minute

function allowed(subject) {
  const now = Date.now();
  const entry = limits.get(subject) || { count: 0, last: now };
  if (now - entry.last > WINDOW) {
    entry.count = 1;
    entry.last = now;
  } else {
    entry.count += 1;
  }
  limits.set(subject, entry);
  return entry.count <= RATE;
}

app.use((req, res, next) => {
  const cert = req.connection.getPeerCertificate?.();
  if (!cert || !cert.subject) {
    return res.send(403, { error: 'missing client certificate' });
  }
  const subject = cert.subject; // e.g., CN=user-123
  if (!allowed(subject)) {
    return res.send(429, { error: 'rate limit exceeded' });
  }
  return next();
});

app.get('/api/v1/resource', (req, res, next) => {
  res.send({ hello: 'world' });
  return next();
});

app.listen(8080, () => {
  console.log('API listening on port 8080');
});

Using a shared rate store for distributed deployments

In production, prefer a shared store such as Redis to coordinate limits across multiple instances. This ensures mTLS-validated identities are consistently limited regardless of which node handles the request.

const redis = require('redis');
const client = redis.createClient({ url: 'redis://localhost:6379' });
await client.connect();

async function isAllowed(subject) {
  const key = `rate:${subject}`;
  // Increment and set expiry if new key
  const current = await client.incr(key);
  if (current === 1) await client.expire(key, 60); // 60 seconds window
  return current <= RATE;
}

app.use(async (req, res, next) => {
  const cert = req.connection.getPeerCertificate?.();
  if (!cert || !cert.subject) {
    return res.send(403, { error: 'missing client certificate' });
  }
  const allowed = await isAllowed(cert.subject);
  if (!allowed) {
    return res.send(429, { error: 'rate limit exceeded' });
  }
  return next();
});

Additional hardening recommendations

  • Bind rate limits to the certificate subject or a mapped user ID to prevent rotation abuse.
  • Enforce both per-identity and global limits to protect backend services.
  • Log rejected requests with certificate identifiers for audit and anomaly detection.
  • Rotate server-side certificates and update the CA bundle without breaking client validation workflows.

Implementing these patterns ensures that mTLS authentication and rate limiting work together: mTLS provides strong client identity, while explicit rate controls prevent authenticated clients from abusing the API.

Frequently Asked Questions

Does mTLS alone prevent API rate abuse?
No. Mutual TLS authenticates clients but does not enforce request volume limits. You must add explicit rate limiting keyed to the authenticated certificate subject to prevent abuse.
How should rate limits be keyed in an mTLS setup?
Key limits by a stable identifier from the client certificate, such as the subject (e.g., CN=user-123) or a mapped user ID, and enforce per-identity limits alongside global caps.