Missing Tls in Feathersjs
How Missing Tls Manifests in Feathersjs
Missing TLS in FeathersJS applications creates several critical attack vectors that directly impact API security. When FeathersJS services communicate over unencrypted HTTP, attackers can intercept credentials, session tokens, and sensitive business data through man-in-the-middle attacks.
The most common manifestation occurs in authentication flows. FeathersJS authentication plugins like @feathersjs/authentication exchange JWT tokens and user credentials over the network. Without TLS, these tokens travel in plaintext, allowing attackers on the same network to capture valid authentication tokens and impersonate users.
Consider a FeathersJS application using socket.io for real-time communication. By default, socket.io may negotiate an insecure connection if TLS isn't explicitly configured. An attacker can intercept WebSocket traffic, capture real-time data streams, and potentially inject malicious messages into the communication channel.
Database connections represent another critical path. Many FeathersJS applications connect to MongoDB, PostgreSQL, or other databases from the same server that hosts the API. While database connections might be internal, configuration files containing database credentials often travel over HTTP during deployment or configuration management, exposing connection strings and credentials.
API documentation and OpenAPI specs hosted by FeathersJS apps frequently contain sensitive information. Without TLS, attackers can passively monitor traffic to discover API endpoints, data models, and potentially sensitive schema information that helps craft targeted attacks.
Third-party service integrations compound the risk. FeathersJS applications commonly integrate with payment processors, email services, or cloud storage. These integrations often exchange API keys, customer data, or transaction details. Missing TLS exposes these integration credentials and the data they protect.
Configuration drift poses a particular challenge in FeathersJS. Developers might configure TLS for production but forget to enable it in staging or development environments. This inconsistency creates confusion about when TLS is actually required, leading to accidental deployments of insecure configurations.
Feathersjs-Specific Detection
Detecting missing TLS in FeathersJS applications requires examining both configuration files and runtime behavior. Start by inspecting your FeathersJS configuration files for HTTPS settings.
// config/default.json
{
"host": "localhost",
"port": 3030,
"protocol": "http" // This should be "https" in production
}
// config/production.json
{
"host": "api.example.com",
"port": 443,
"protocol": "https",
"https": {
"key": "path/to/ssl.key",
"cert": "path/to/ssl.crt",
"ca": "path/to/ca.crt"
}
}
Look for missing or misconfigured HTTPS properties in your FeathersJS app initialization:
// app.js - Insecure configuration
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const authentication = require('@feathersjs/authentication');
const app = express(feathers());
app.configure(express.rest());
app.configure(authentication()); // No HTTPS configuration
Run a security scan with middleBrick to automatically detect missing TLS across your FeathersJS API endpoints. The scanner tests whether your API responds to HTTP requests and identifies endpoints that lack proper TLS enforcement.
middleBrick's TLS detection specifically checks for:
- HTTP endpoints that should be HTTPS-only
- Missing HSTS headers that prevent protocol downgrade attacks
- Mixed content issues where HTTPS pages load HTTP resources
- API endpoints accessible without TLS encryption
For FeathersJS applications using socket.io, verify WebSocket security configuration:
// Insecure - allows unencrypted WebSocket connections
const socketio = require('socket.io');
const io = socketio(server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
// Secure - enforces WSS (WebSocket Secure)
const io = socketio(server, {
cors: {
origin: "https://yourdomain.com",
methods: ["GET", "POST"]
},
allowEIO3: false, // Disallow old, insecure protocols
perMessageDeflate: false
});
Check your FeathersJS authentication configuration for secure cookie settings:
// Insecure authentication setup
app.configure(authentication({
cookie: {
httpOnly: true,
secure: false // Should be true for HTTPS
}
}));
// Secure authentication setup
app.configure(authentication({
cookie: {
httpOnly: true,
secure: true, // Only send over HTTPS
sameSite: 'strict'
}
}));
Feathersjs-Specific Remediation
Securing FeathersJS applications with TLS requires configuration changes across multiple components. Start by implementing proper HTTPS server configuration using Node.js's built-in HTTPS module.
// secure-app.js
const https = require('https');
const fs = require('fs');
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const authentication = require('@feathersjs/authentication');
const app = express(feathers());
app.configure(express.rest());
app.configure(authentication());
// Load SSL certificates
const options = {
key: fs.readFileSync('path/to/private/key.pem'),
cert: fs.readFileSync('path/to/certificate.pem'),
ca: fs.readFileSync('path/to/ca-bundle.pem')
};
// Create HTTPS server
const server = https.createServer(options, app);
// Start server on port 443
server.listen(443, () => {
console.log('FeathersJS API running securely on https://localhost');
});
For development environments, use a reverse proxy like Nginx or Apache to handle TLS termination while your FeathersJS app runs on HTTP internally:
# nginx.conf
upstream feathers_app {
server localhost:3030;
}
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /path/to/yourdomain.com.crt;
ssl_certificate_key /path/to/yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
location / {
proxy_pass http://feathers_app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Configure FeathersJS to trust the proxy headers for secure connections:
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const authentication = require('@feathersjs/authentication');
const app = express(feathers());
app.configure(express.rest());
app.configure(authentication());
// Configure proxy support
app.set('trust proxy', 1); // Trust first proxy (nginx)
// Add security middleware
app.use((req, res, next) => {
// Redirect HTTP to HTTPS
if (req.headers['x-forwarded-proto'] === 'http') {
return res.redirect(301, `https://${req.headers.host}${req.url}`);
}
next();
});
Implement HSTS (HTTP Strict Transport Security) headers to prevent protocol downgrade attacks:
const helmet = require('helmet');
app.configure(helmet({
hsts: {
maxAge: 31536000, // 1 year
includeSubDomains: true,
preload: true
}
}));
Secure your FeathersJS authentication configuration with proper cookie settings:
app.configure(authentication({
cookie: {
httpOnly: true,
secure: true, // Only send over HTTPS
sameSite: 'strict',
maxAge: 900000 // 15 minutes
},
jwt: {
header: { typ: 'access' },
audience: 'https://yourdomain.com',
issuer: 'feathers',
expiresIn: '1d'
}
}));
For WebSocket security in FeathersJS, configure socket.io to require secure connections:
const io = require('socket.io')(server, {
cors: {
origin: ["https://yourdomain.com"],
methods: ["GET", "POST"]
},
allowEIO3: false,
perMessageDeflate: false,
// Force secure connections
allowRequest: (req, callback) => {
callback(null, req.secure);
}
});
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 |