Security
Current security status and required improvements for the TrickBook backend.
Critical Issues
The following issues must be addressed before any further development.
1. Exposed Credentials
Status: CRITICAL
The .env file contains plaintext credentials that may be committed to git:
# EXPOSED - Rotate these immediately
ATLAS_URI=mongodb+srv://[REDACTED]@cluster.mongodb.net/...
AWS_KEY=[REDACTED]
AWS_SECRET=[REDACTED]
EMAIL_PASSWORD=[REDACTED]
Fix:
- Rotate ALL credentials immediately
- Add
.envto.gitignore - Use secrets manager (AWS Secrets Manager, Doppler, etc.)
- Create
.env.examplewith placeholder values
2. Hardcoded JWT Secret
Status: CRITICAL
// Current code - INSECURE
jwt.sign(payload, "jwtPrivateKey");
Fix:
jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });
3. No Token Expiration
Status: CRITICAL
JWT tokens never expire, meaning a leaked token grants permanent access.
Fix:
const token = jwt.sign(payload, process.env.JWT_SECRET, {
expiresIn: '1h' // Short-lived access token
});
// Implement refresh tokens for better UX
const refreshToken = jwt.sign(
{ _id: user._id },
process.env.REFRESH_SECRET,
{ expiresIn: '7d' }
);
4. End-of-Life Node.js
Status: CRITICAL
Node.js 12.6.x reached end-of-life in April 2022. No security patches available.
Fix:
// package.json
{
"engines": {
"node": ">=18.0.0"
}
}
High Priority Issues
5. Outdated helmet
Current: 3.22.0 (2019) Latest: 7.x
Missing security headers and protections.
Fix:
npm install helmet@latest
const helmet = require('helmet');
app.use(helmet());
6. No Rate Limiting
Login and API endpoints have no protection against brute force attacks.
Fix:
npm install express-rate-limit
const rateLimit = require('express-rate-limit');
// Strict limit for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5,
message: 'Too many login attempts, try again later'
});
router.post('/auth', authLimiter, loginHandler);
// General API limit
const apiLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100
});
app.use('/api/', apiLimiter);
7. CORS Wildcard
Current:
app.use(cors()); // Allows all origins
Fix:
const corsOptions = {
origin: [
'https://thetrickbook.com',
'https://www.thetrickbook.com',
'https://admin.thetrickbook.com'
],
credentials: true
};
app.use(cors(corsOptions));
8. Unrestricted Public Endpoints
These endpoints expose data without authentication:
| Endpoint | Risk |
|---|---|
GET /api/users/all | Exposes all user emails |
GET /api/listings/all | Exposes all user data |
GET /api/spots | May be intentional |
Fix: Add authentication or remove if not needed.
Medium Priority Issues
9. Weak Password Requirements
Current:
password: Joi.string().min(5).required()
Fix:
password: Joi.string()
.min(8)
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
.required()
.messages({
'string.pattern.base': 'Password must contain uppercase, lowercase, and number'
})
10. No Input Sanitization
User input used directly in regex patterns:
// Vulnerable
{ name: { $regex: userInput, $options: "i" } }
Fix:
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
{ name: { $regex: escapeRegex(userInput), $options: "i" } }
11. Missing HTTPS Redirect
Ensure all traffic uses HTTPS:
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
return res.redirect(`https://${req.header('host')}${req.url}`);
}
next();
});
12. No Request Size Limits
Large payloads could cause DoS:
app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ limit: '10kb', extended: true }));
Security Checklist
Authentication
- Move JWT secret to environment variable
- Add token expiration (1 hour)
- Implement refresh tokens
- Add password complexity requirements
- Add account lockout after failed attempts
Authorization
- Review all public endpoints
- Add authentication to
/api/users/all - Verify admin checks on all admin routes
Network
- Update CORS whitelist
- Add rate limiting
- Enforce HTTPS
- Add request size limits
Dependencies
- Upgrade Node.js to 18+
- Update helmet to 7.x
- Update jsonwebtoken to 9.x
- Update joi to 17.x
- Run
npm auditand fix vulnerabilities
Credentials
- Rotate MongoDB password
- Rotate AWS access keys
- Rotate email password
- Create new JWT secret
- Add
.envto.gitignore - Set up secrets manager
Monitoring
- Add error logging (Winston/Pino)
- Set up Sentry for error tracking
- Monitor for suspicious activity
- Set up alerts for failed auth attempts
Secure Configuration Template
// index.js - Secure setup
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const app = express();
// Security headers
app.use(helmet());
// CORS whitelist
app.use(cors({
origin: ['https://thetrickbook.com'],
credentials: true
}));
// Rate limiting
app.use(rateLimit({
windowMs: 60 * 1000,
max: 100
}));
// Request size limits
app.use(express.json({ limit: '10kb' }));
// HTTPS redirect (behind proxy)
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
return res.redirect(301, `https://${req.header('host')}${req.url}`);
}
next();
});
// Validate required env vars
const required = ['ATLAS_URI', 'JWT_SECRET', 'AWS_KEY'];
required.forEach(key => {
if (!process.env[key]) {
console.error(`Missing required env var: ${key}`);
process.exit(1);
}
});