HIGH api key exposurerestifymutual tls

Api Key Exposure in Restify with Mutual Tls

Api Key Exposure in Restify with Mutual Tls

Restify is a Node.js-focused web framework often used to build APIs that also act as clients. When you combine Restify with mutual TLS (mTLS), the intent is to strengthen transport-layer identity: the server verifies the client certificate, and the client presents a certificate. However, this setup can inadvertently create or expose an Api Key Exposure risk when developers mistakenly believe mTLS alone replaces application-level authentication.

In an mTLS configuration, the client certificate provides identity, but it does not automatically carry or protect an API key. If the API key is still required—for example, passed as a header like x-api-key or embedded in request parameters—and the TLS channel is not strictly enforced for all endpoints, two issues arise. First, the API key may traverse the network in cleartext if a non-TLS or misconfigured route exists. Second, logs, error messages, or HTTP referrers might inadvertently include the key. Even with mTLS, if the application code forwards requests to downstream services without stripping or protecting the key, the key can be exposed beyond the intended endpoint.

The specific combination increases risk when mTLS is enforced only on selected routes. An attacker who can reach an unprotected route or a legacy endpoint might capture the API key in transit or from logs. Additionally, if the client certificate is compromised, the attacker might pair it with a stolen API key to masquerade as a legitimate client. This mirrors patterns seen in broken authentication and authorization flaws (BOLA/IDOR), where trust in one factor (the certificate) is assumed to cover all security requirements. MiddleBrick scans detect such inconsistencies by correlating unauthenticated attack surface tests with spec-defined authentication mechanisms, highlighting when transport-layer controls do not align with application-layer requirements.

Real-world examples include configurations where the API key is stored in environment variables and accidentally logged by Restify error handlers, or where a developer disables TLS verification on a subset of routes for debugging and forgets to remove it. Another scenario: an mTLS-enabled Restify service that exposes a health-check endpoint without requiring the API key, allowing enumeration of valid keys through timing differences. These cases illustrate that mTLS secures the pipe but does not inherently prevent the application from mishandling the key itself.

To assess this risk, MiddleBrick evaluates whether authentication mechanisms are consistently applied across all endpoints, whether the OpenAPI spec correctly documents security schemes, and whether runtime behavior matches the declared TLS and authentication requirements. This ensures that the presence of mTLS does not create a false sense of security regarding Api Key Exposure.

Mutual Tls-Specific Remediation in Restify

Remediation focuses on ensuring mTLS is uniformly enforced, API keys are protected at the application layer, and configurations avoid mixed-mode pitfalls. Below are concrete steps and code examples for a Restify server that correctly uses mutual TLS while safeguarding API keys.

1. Enforce mTLS across all routes

Configure the Restify server to require client certificates for every request. Do not create exceptions for development or debugging routes.

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

const server = restify.createServer({
  certificate: fs.readFileSync('/path/to/server-cert.pem'),
  key: fs.readFileSync('/path/to/server-key.pem'),
  ca: fs.readFileSync('/path/to/ca-cert.pem'),
  requestCert: true,
  rejectUnauthorized: true
});

server.get('/health', (req, res, next) => {
  // Health checks still require a valid client cert due to rejectUnauthorized
  res.send(200, { status: 'ok' });
  return next();
});

server.listen(8080, () => {
  console.log('Server listening');
});

2. Separate transport identity from application identity

Do not rely on the client certificate to convey the API key. Keep the API key as a separate application-level credential (e.g., in an Authorization header), and validate it independently of the TLS client certificate.

server.use((req, res, next) => {
  const cert = req.client.verifiedCert || req.connection.getPeerCertificate();
  if (!cert || !cert.fingerprint) {
    return next(new restify.errors.ForbiddenError('Client certificate required'));
  }
  // Application-level API key validation
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== process.env.API_KEY) {
    return next(new restify.errors.UnauthorizedError('Invalid API key'));
  }
  return next();
});

server.get('/data', (req, res, next) => {
  res.send(200, { data: 'protected' });
  return next();
});

3. Avoid insecure logging and referrer leaks

Ensure request and response bodies, headers, and URLs containing API keys are not logged. Sanitize logs and disable automatic logging of sensitive headers.

const bunyan = require('bunyan');
const log = bunyan.createLogger({ name: 'api' });

server.on('after', (req, res, route, err) => {
  // Explicitly exclude sensitive headers
  const filteredHeaders = { ...req.headers };
  delete filteredHeaders['x-api-key'];
  log.info({ reqId: req.id, method: req.method, url: req.url, headers: filteredHeaders });
});

4. Use strict TLS options and disable insecure protocols

Configure the server to use strong ciphers and to reject outdated protocols. Do not disable certificate verification for any route.

server.tlsEnabled = true;
server.on('tlsClientError', (err, req) => {
  // Handle mTLS errors without exposing sensitive data
  req.log.error({ err: err.message }, 'TLS client error');
});

5. Validate and rotate keys programmatically

Do not hardcode API keys. Use environment variables or a secure secret manager, and implement rotation policies. Ensure keys are scoped and have minimal required permissions.

// Example: validate against a secret manager (pseudocode)
async function validateApiKey(key) {
  const isValid = await secretManager.verify('api-key', key);
  return isValid;
}

6. Use the MiddleBrick CLI to verify your configuration

Run middlebrick scan <url> to test whether your endpoints consistently enforce mTLS and whether API key handling aligns with your security posture. The scan will highlight inconsistencies between declared authentication in the OpenAPI spec and runtime behavior.

7. CI/CD integration for ongoing enforcement

With the MiddleBrick GitHub Action, add API security checks to your CI/CD pipeline to fail builds if risk scores degrade. This helps catch regressions where mTLS or API key handling is inadvertently weakened.

8. MCP Server for developer workflows

Scan APIs directly from your AI coding assistant using the MiddleBrick MCP Server. This helps you validate that new endpoints you add maintain mTLS and API key protections as intended.

Frequently Asked Questions

Does mTLS alone protect an API key in Restify?
No. mTLS secures the transport and verifies client identity, but it does not protect an API key if the key is still transmitted as a header or parameter. The API key must be validated as a separate application-level credential, and all routes must enforce TLS uniformly to prevent exposure.
How can I detect accidental API key exposure in Restify with mTLS?
Use MiddleBrick to scan your API. It runs unauthenticated checks that correlate TLS requirements with authentication schemes, flags endpoints that lack required credentials, and reviews logs and spec definitions for inconsistencies that could lead to key exposure.