Missing Tls in Express with Api Keys
Missing Tls in Express with Api Keys — how this specific combination creates or exposes the vulnerability
When an Express API uses API keys for authorization but does not enforce Transport Layer Security (TLS), the keys are transmitted in cleartext. This combination creates a critical exposure because API keys are often long-lived credentials that authorize access to sensitive endpoints. Without TLS, any intermediary on the network path can observe or modify unencrypted HTTP traffic, leading to credential interception and potential misuse.
In practice, a client sends an API key in an HTTP header such as Authorization: ApiKey 12345-abcdef. If the server listens only on HTTP (port 80) or terminates TLS incorrectly (for example, accepting cleartext HTTP even when a certificate is configured), an attacker positioned on the same network or path can capture the key using standard packet inspection tools. Once obtained, the attacker can impersonate the legitimate client and invoke any operation permitted by the key, which may include reading or modifying data covered by the key's scope.
The risk is compounded when the API exposes sensitive endpoints—such as administrative functions, user data export, or payment processing—under the same unencrypted channel. Because API keys are often static and lack the short lifetime of session tokens, the window for exploitation is large. Attack patterns like credential sniffing on shared or compromised networks, misconfigured load balancers that pass traffic without encryption, and insecure redirects that downgrade HTTPS to HTTP are common real-world vectors that exploit Missing TLS.
Moreover, if the API specification (for example, an OpenAPI 3.0 document) describes security schemes using apiKey in in: header but the server does not require or enforce HTTPS, the documented security expectation is not met. This mismatch between specification and implementation can mislead developers and automated tools into assuming protection that does not exist. MiddleBrick’s OpenAPI/Swagger analysis resolves $ref definitions and cross-references them with runtime findings to highlight such discrepancies, ensuring that security schemes requiring TLS are actually served over encrypted connections.
Api Keys-Specific Remediation in Express — concrete code fixes
To remediate Missing TLS in Express when using API keys, enforce HTTPS for all traffic and validate that API keys are only accepted over encrypted connections. Below are concrete, syntactically correct examples demonstrating secure configuration and usage.
1. Enforce HTTPS in Express
Use the built-in https module with a valid certificate and private key. Ensure the server does not listen on plain HTTP, or redirect HTTP to HTTPS.
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
const options = {
key: fs.readFileSync('/path/to/private-key.pem'),
cert: fs.readFileSync('/path/to/certificate.pem'),
};
// Security middleware: redirect HTTP to HTTPS if running behind a proxy, or simply avoid HTTP server
app.use((req, res, next) => {
if (req.headers['x-forwarded-proto'] !== 'https' && process.env.NODE_ENV === 'production') {
return res.redirect(301, `https://${req.headers.host}${req.url}`);
}
next();
});
// Start HTTPS server only
https.createServer(options, app).listen(443, () => {
console.log('HTTPS server running on port 443');
});
2. Validate API Keys only over secure channels
Implement a middleware that checks for the API key and ensures the request is using TLS. This example assumes keys are stored securely (for example, in environment variables) and compared in constant time to avoid timing attacks.
const crypto = require('crypto');
const express = require('express');
const app = express();
const API_KEYS = new Set([
process.env.API_KEY_PROD, // expected format: 64-hex or base64
]);
function timingSafeCompare(a, b) {
return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}
app.use((req, res, next) => {
const provided = req.headers['x-api-key'] || req.headers['authorization']?.replace('ApiKey ', '');
if (!provided) {
return res.status(401).json({ error: 'API key missing' });
}
// Ensure request is over HTTPS
const isHttps = req.secure || req.headers['x-forwarded-proto']?.startsWith('https');
if (!isHttps) {
return res.status(403).json({ error: 'TLS required' });
}
const isValid = API_KEYS.has(provided) || Array.from(API_KEYS).some(key => timingSafeCompare(Buffer.from(provided), Buffer.from(key)));
if (!isValid) {
return res.status(403).json({ error: 'Invalid API key' });
}
next();
});
app.get('/v1/resource', (req, res) => {
res.json({ data: 'secure data' });
});
app.listen(8080, () => console.log('App listening on port 8080 with TLS enforcement'));
3. Complementary practices
- Use HTTP Strict Transport Security (HSTS) headers to instruct browsers to only use HTTPS.
- Rotate API keys regularly and scope them to least privilege via the Dashboard or CLI configuration.
- Verify that any reverse proxy or load balancer preserves and enforces TLS before traffic reaches Express.
These steps ensure that API keys are protected in transit, reducing the risk of interception and unauthorized use. MiddleBrick’s scans can verify that your endpoints require TLS and that API key-bearing requests are served only over encrypted channels.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |