Backend Development with Security Focus
Secure backend development prevents vulnerabilities while maintaining functionality. Every endpoint, database query, and user input is a potential attack vector.
Core Security Principles
Golden rule: Never trust client input. Always validate, sanitize, and verify.
- Defense in Depth - Multiple layers of security controls
- Principle of Least Privilege - Grant minimum necessary permissions
- Fail Securely - Fail to a secure state when errors occur
- Assume Breach - Design assuming attackers are already inside
- Security by Design - Build security from the start, not as afterthought
API Security
Key Principles:
- Use UUIDs instead of sequential IDs to prevent enumeration
- Implement rate limiting on all endpoints
- Apply authentication middleware before business logic
- Validate all input formats (UUID, email, etc.)
- Use parameterized queries to prevent SQL injection
- Return only necessary fields (don't expose passwords, internal data)
- Version your APIs (
/api/v1/, /api/v2/)
- Limit request payload sizes (JSON: 10kb, files: 5MB max)
- Whitelist allowed file types for uploads
- Always verify authorization (user owns resource or has permissions)
Authentication & Authorization
JWT Best Practices:
- Use strong secrets (64+ characters, generate with
crypto.randomBytes(64).toString('hex'))
- Short-lived access tokens (15 min) + long-lived refresh tokens (7 days)
- Store minimal payload (user ID only, no sensitive data)
- Validate token type (access vs refresh) and expiration
- Use separate secrets for access and refresh tokens
- Support secret rotation for zero-downtime updates
Password Security:
- Enforce strong passwords (12+ chars, uppercase, lowercase, number, special char)
- Hash with bcrypt (salt rounds: 12+)
- Never store plaintext passwords
- Implement account lockout (5 failed attempts = 15 min lock)
- Use generic error messages (don't reveal if email exists)
- Consider MFA for sensitive operations
Role-Based Access Control (RBAC):
- Define roles (Admin, User, Guest) and permissions separately
- Map roles to permissions explicitly
- Check authentication first, then authorization
- Create reusable middleware for permission checks
- Use enums for type safety
- Always verify resource ownership (IDOR prevention)
Input Validation & Sanitization
Schema Validation (use Zod, Joi, or similar):
- Define schemas for all API inputs (body, params, query)
- Validate types, formats, lengths, patterns
- Use
.trim(), .toLowerCase(), .optional(), .default() as needed
- Return detailed validation errors (field + message)
- Create reusable validation middleware
SQL Injection Prevention:
- ALWAYS use parameterized queries (
$1, $2 placeholders)
- NEVER concatenate strings in SQL queries
- Use ORMs (Prisma, TypeORM) when possible for built-in protection
- Escape special characters if parameterization isn't possible
XSS Prevention:
- Sanitize HTML input with DOMPurify or similar
- Whitelist allowed tags and attributes
- Escape output when rendering user content
- Use Content Security Policy headers
- Prefer storing plain text; sanitize only when HTML is necessary
Path Traversal Prevention:
- Validate filenames with regex (alphanumeric, dash, underscore, dot only)
- Use
path.resolve() and check resolved path starts with allowed directory
- Never trust user-provided paths directly
- Whitelist allowed file extensions
- Check file existence before serving
Database Security
Connection Security:
- Use SSL/TLS in production (rejectUnauthorized: true)
- Store credentials in environment variables
- Configure connection pool limits (max: 20, timeout: 2000ms)
- Handle connection errors gracefully
- Use separate read-only users for reporting queries
Query Security:
- Always use parameterized queries (prevents SQL injection)
- Wrap multi-step operations in transactions
- Use ROLLBACK on errors
- Log query errors (but not sensitive data)
- Release connections after use
Data Encryption at Rest:
- Encrypt sensitive fields (credit cards, SSN, PII)
- Use AES-256-GCM for encryption
- Store IV and auth tag with encrypted data
- Use strong encryption keys (32 bytes, in hex)
- Never store encryption keys in code - use environment variables
Error Handling
Secure Error Responses:
- Never expose stack traces or internal details in production
- Log full error details server-side (path, method, user, stack)
- Return generic messages to clients ("Internal server error")
- Use custom error classes with isOperational flag
- Differentiate between operational errors (404, 400) and programmer errors (500)
- Include detailed errors only in development mode
- Use centralized error handling middleware
Security Headers & CORS
Essential Security Headers (use helmet.js):
X-Frame-Options: DENY - Prevent clickjacking
X-Content-Type-Options: nosniff - Prevent MIME sniffing
X-XSS-Protection: 1; mode=block - Enable XSS filter
Strict-Transport-Security - Force HTTPS (max-age=31536000; includeSubDomains)
Content-Security-Policy - Define allowed content sources
Referrer-Policy: strict-origin-when-cross-origin - Control referrer info
Permissions-Policy - Disable unused browser features
CORS Configuration:
- Never use
origin: '*' in production
- Whitelist specific origins in environment variables
- Allow localhost only in development
- Enable credentials for cookie-based auth
- Cache preflight requests (maxAge: 86400)
- Specify allowedHeaders (Content-Type, Authorization)
- Set exposedHeaders for pagination (X-Total-Count)
Secrets Management
Environment Variables:
- Never hardcode secrets in source code
- Use
.env files (add to .gitignore)
- Validate all environment variables on startup using Zod
- Enforce minimum lengths for secrets (64+ characters)
- Validate formats (email, URL, specific prefixes like
sk_)
- Exit process if required secrets are missing
- Use cloud secret managers in production (AWS Secrets Manager, Vault)
Secrets Rotation:
- Support multiple active secrets for zero-downtime rotation
- Try current secret first, fallback to previous
- Set expiration dates for old secrets
- Rotate secrets quarterly or after suspected compromise
Rate Limiting & DoS Prevention
Rate Limiting Strategy:
- Use Redis store for distributed rate limiting
- General API: 100 requests per 15 minutes
- Auth endpoints: 5 attempts per hour (skip successful requests)
- Key by user ID if authenticated, otherwise IP
- Progressive limits (authenticated users get higher limits)
- Return 429 status with clear error message
Request Throttling:
- Slow down after threshold (50 requests) before blocking
- Add incremental delays (500ms per extra request)
- Set maximum delay (20 seconds)
- Prevents aggressive blocking while discouraging abuse
Logging & Monitoring
Structured Logging (use Winston or Pino):
- Use JSON format with timestamps
- Log levels: error, warn, info, debug
- Include context: method, URL, status, duration, userId, IP
- Separate error.log and combined.log files
- Console logging in development only
- Never log sensitive data (passwords, tokens, credit cards)
- Sanitize objects before logging (redact sensitive fields)
Security Event Monitoring:
- Track critical events (failed logins, invalid tokens, permission denials)
- Log IP, user agent, path, timestamp for all security events
- Alert on SQL injection attempts, XSS attempts
- Integrate with monitoring services (Sentry, DataDog, New Relic)
- Set up alerts for suspicious patterns (multiple failed logins, rate limit exceeded)
- Review logs regularly for anomalies
Common Vulnerabilities (OWASP Top 10)
SQL Injection:
- Always use parameterized queries (
$1, $2) - NEVER string concatenation
- Use ORMs (Prisma, TypeORM) for built-in protection
Cross-Site Scripting (XSS):
- Sanitize HTML input (DOMPurify)
- Escape output when rendering
- Use Content Security Policy headers
Cross-Site Request Forgery (CSRF):
- Use CSRF tokens for cookie-based auth (csurf package)
- Set httpOnly, secure, sameSite: 'strict' on cookies
- For JWT APIs, validate origin and use proper CORS
Insecure Deserialization:
- NEVER use eval() or Function() with user input
- Use JSON.parse + schema validation only
- Avoid vm.runInNewContext and similar
XML External Entities (XXE):
- Disable external entity resolution in XML parsers
- Use JSON instead of XML when possible
Insecure Direct Object References (IDOR):
- Always verify resource ownership before returning data
- Check
resource.userId === req.user.uuid or admin status
- Use UUIDs instead of sequential IDs
Testing Security
Unit Tests:
- Test password validation (reject weak, accept strong)
- Test password hashing (bcrypt format, verify correct/incorrect)
- Test authorization (401 without token, 403 without permissions)
- Test input validation (reject malicious patterns)
Integration Tests:
- Test SQL injection attempts (should return 400, not all data)
- Test rate limiting (10+ requests should trigger 429)
- Test IDOR (users can't access others' resources)
- Test CSRF protection on state-changing endpoints
Automated Security Scanning:
npm audit - Check dependencies for vulnerabilities
npx snyk test - Continuous vulnerability monitoring
eslint-plugin-security - Static analysis for security issues
gitleaks detect - Check for hardcoded secrets in code
- Run scans in CI/CD pipeline
Implementation Guidelines
IMPORTANT: Do NOT create summary markdown files, documentation files, or README files unless explicitly requested by the user.
Best Practices
- Never Trust User Input - Validate, sanitize, and escape all input regardless of source
- Use Parameterized Queries - Always use prepared statements for database queries
- Implement Proper Authentication - Use industry-standard methods (JWT, OAuth) with secure configuration
- Apply Principle of Least Privilege - Grant minimum necessary permissions to users and services
- Encrypt Sensitive Data - Use encryption at rest and in transit (TLS/SSL)
- Keep Dependencies Updated - Regularly update packages and scan for vulnerabilities
- Implement Rate Limiting - Prevent abuse and DoS attacks on all endpoints
- Log Security Events - Monitor and alert on suspicious activities
- Handle Errors Securely - Never expose stack traces or internal details to clients
- Use Security Headers - Implement helmet.js and configure CSP, HSTS, etc.
- Validate Environment Config - Ensure all required secrets are present on startup
- Implement Request Timeouts - Prevent resource exhaustion from slow requests
- Use HTTPS Everywhere - Never transmit sensitive data over unencrypted connections
- Implement CSRF Protection - For cookie-based auth, use CSRF tokens
- Regular Security Audits - Conduct code reviews and penetration testing
- Have an Incident Response Plan - Prepare for security breaches before they happen
- Minimize Attack Surface - Disable unnecessary features and endpoints
- Use Security Linters - Integrate security scanning in CI/CD pipeline
- Implement Proper Session Management - Use secure, httpOnly cookies with appropriate expiration
- Document Security Decisions - Maintain a threat model and security architecture docs
References
1---2name: backend-security3description: Backend development with security-first approach. Use when building APIs, handling data, implementing authentication, or addressing security vulnerabilities.4---5
6# Backend Development with Security Focus
7
8Secure backend development prevents vulnerabilities while maintaining functionality. Every endpoint, database query, and user input is a potential attack vector.
9
10## Core Security Principles
11
12**Golden rule**: Never trust client input. Always validate, sanitize, and verify.
13
141. **Defense in Depth** - Multiple layers of security controls
152. **Principle of Least Privilege** - Grant minimum necessary permissions
163. **Fail Securely** - Fail to a secure state when errors occur
174. **Assume Breach** - Design assuming attackers are already inside
185. **Security by Design** - Build security from the start, not as afterthought
19
20## API Security
21
22**Key Principles**:
23- Use UUIDs instead of sequential IDs to prevent enumeration
24- Implement rate limiting on all endpoints
25- Apply authentication middleware before business logic
26- Validate all input formats (UUID, email, etc.)
27- Use parameterized queries to prevent SQL injection
28- Return only necessary fields (don't expose passwords, internal data)
29- Version your APIs (`/api/v1/`, `/api/v2/`)
30- Limit request payload sizes (JSON: 10kb, files: 5MB max)
31- Whitelist allowed file types for uploads
32- Always verify authorization (user owns resource or has permissions)
33
34## Authentication & Authorization
35
36**JWT Best Practices**:
37- Use strong secrets (64+ characters, generate with `crypto.randomBytes(64).toString('hex')`)
38- Short-lived access tokens (15 min) + long-lived refresh tokens (7 days)
39- Store minimal payload (user ID only, no sensitive data)
40- Validate token type (access vs refresh) and expiration
41- Use separate secrets for access and refresh tokens
42- Support secret rotation for zero-downtime updates
43
44**Password Security**:
45- Enforce strong passwords (12+ chars, uppercase, lowercase, number, special char)
46- Hash with bcrypt (salt rounds: 12+)
47- Never store plaintext passwords
48- Implement account lockout (5 failed attempts = 15 min lock)
49- Use generic error messages (don't reveal if email exists)
50- Consider MFA for sensitive operations
51
52**Role-Based Access Control (RBAC)**:
53- Define roles (Admin, User, Guest) and permissions separately
54- Map roles to permissions explicitly
55- Check authentication first, then authorization
56- Create reusable middleware for permission checks
57- Use enums for type safety
58- Always verify resource ownership (IDOR prevention)
59
60## Input Validation & Sanitization
61
62**Schema Validation** (use Zod, Joi, or similar):
63- Define schemas for all API inputs (body, params, query)
64- Validate types, formats, lengths, patterns
65- Use `.trim()`, `.toLowerCase()`, `.optional()`, `.default()` as needed
66- Return detailed validation errors (field + message)
67- Create reusable validation middleware
68
69**SQL Injection Prevention**:
70- ALWAYS use parameterized queries (`$1`, `$2` placeholders)
71- NEVER concatenate strings in SQL queries
72- Use ORMs (Prisma, TypeORM) when possible for built-in protection
73- Escape special characters if parameterization isn't possible
74
75**XSS Prevention**:
76- Sanitize HTML input with DOMPurify or similar
77- Whitelist allowed tags and attributes
78- Escape output when rendering user content
79- Use Content Security Policy headers
80- Prefer storing plain text; sanitize only when HTML is necessary
81
82**Path Traversal Prevention**:
83- Validate filenames with regex (alphanumeric, dash, underscore, dot only)
84- Use `path.resolve()` and check resolved path starts with allowed directory
85- Never trust user-provided paths directly
86- Whitelist allowed file extensions
87- Check file existence before serving
88
89## Database Security
90
91**Connection Security**:
92- Use SSL/TLS in production (rejectUnauthorized: true)
93- Store credentials in environment variables
94- Configure connection pool limits (max: 20, timeout: 2000ms)
95- Handle connection errors gracefully
96- Use separate read-only users for reporting queries
97
98**Query Security**:
99- Always use parameterized queries (prevents SQL injection)
100- Wrap multi-step operations in transactions
101- Use ROLLBACK on errors
102- Log query errors (but not sensitive data)
103- Release connections after use
104
105**Data Encryption at Rest**:
106- Encrypt sensitive fields (credit cards, SSN, PII)
107- Use AES-256-GCM for encryption
108- Store IV and auth tag with encrypted data
109- Use strong encryption keys (32 bytes, in hex)
110- Never store encryption keys in code - use environment variables
111
112## Error Handling
113
114**Secure Error Responses**:
115- Never expose stack traces or internal details in production
116- Log full error details server-side (path, method, user, stack)
117- Return generic messages to clients ("Internal server error")
118- Use custom error classes with isOperational flag
119- Differentiate between operational errors (404, 400) and programmer errors (500)
120- Include detailed errors only in development mode
121- Use centralized error handling middleware
122
123## Security Headers & CORS
124
125**Essential Security Headers** (use helmet.js):
126- `X-Frame-Options: DENY` - Prevent clickjacking
127- `X-Content-Type-Options: nosniff` - Prevent MIME sniffing
128- `X-XSS-Protection: 1; mode=block` - Enable XSS filter
129- `Strict-Transport-Security` - Force HTTPS (max-age=31536000; includeSubDomains)
130- `Content-Security-Policy` - Define allowed content sources
131- `Referrer-Policy: strict-origin-when-cross-origin` - Control referrer info
132- `Permissions-Policy` - Disable unused browser features
133
134**CORS Configuration**:
135- Never use `origin: '*'` in production
136- Whitelist specific origins in environment variables
137- Allow localhost only in development
138- Enable credentials for cookie-based auth
139- Cache preflight requests (maxAge: 86400)
140- Specify allowedHeaders (Content-Type, Authorization)
141- Set exposedHeaders for pagination (X-Total-Count)
142
143## Secrets Management
144
145**Environment Variables**:
146- Never hardcode secrets in source code
147- Use `.env` files (add to `.gitignore`)
148- Validate all environment variables on startup using Zod
149- Enforce minimum lengths for secrets (64+ characters)
150- Validate formats (email, URL, specific prefixes like `sk_`)
151- Exit process if required secrets are missing
152- Use cloud secret managers in production (AWS Secrets Manager, Vault)
153
154**Secrets Rotation**:
155- Support multiple active secrets for zero-downtime rotation
156- Try current secret first, fallback to previous
157- Set expiration dates for old secrets
158- Rotate secrets quarterly or after suspected compromise
159
160## Rate Limiting & DoS Prevention
161
162**Rate Limiting Strategy**:
163- Use Redis store for distributed rate limiting
164- General API: 100 requests per 15 minutes
165- Auth endpoints: 5 attempts per hour (skip successful requests)
166- Key by user ID if authenticated, otherwise IP
167- Progressive limits (authenticated users get higher limits)
168- Return 429 status with clear error message
169
170**Request Throttling**:
171- Slow down after threshold (50 requests) before blocking
172- Add incremental delays (500ms per extra request)
173- Set maximum delay (20 seconds)
174- Prevents aggressive blocking while discouraging abuse
175
176## Logging & Monitoring
177
178**Structured Logging** (use Winston or Pino):
179- Use JSON format with timestamps
180- Log levels: error, warn, info, debug
181- Include context: method, URL, status, duration, userId, IP
182- Separate error.log and combined.log files
183- Console logging in development only
184- Never log sensitive data (passwords, tokens, credit cards)
185- Sanitize objects before logging (redact sensitive fields)
186
187**Security Event Monitoring**:
188- Track critical events (failed logins, invalid tokens, permission denials)
189- Log IP, user agent, path, timestamp for all security events
190- Alert on SQL injection attempts, XSS attempts
191- Integrate with monitoring services (Sentry, DataDog, New Relic)
192- Set up alerts for suspicious patterns (multiple failed logins, rate limit exceeded)
193- Review logs regularly for anomalies
194
195## Common Vulnerabilities (OWASP Top 10)
196
197**SQL Injection**:
198- Always use parameterized queries (`$1`, `$2`) - NEVER string concatenation
199- Use ORMs (Prisma, TypeORM) for built-in protection
200
201**Cross-Site Scripting (XSS)**:
202- Sanitize HTML input (DOMPurify)
203- Escape output when rendering
204- Use Content Security Policy headers
205
206**Cross-Site Request Forgery (CSRF)**:
207- Use CSRF tokens for cookie-based auth (csurf package)
208- Set httpOnly, secure, sameSite: 'strict' on cookies
209- For JWT APIs, validate origin and use proper CORS
210
211**Insecure Deserialization**:
212- NEVER use eval() or Function() with user input
213- Use JSON.parse + schema validation only
214- Avoid vm.runInNewContext and similar
215
216**XML External Entities (XXE)**:
217- Disable external entity resolution in XML parsers
218- Use JSON instead of XML when possible
219
220**Insecure Direct Object References (IDOR)**:
221- Always verify resource ownership before returning data
222- Check `resource.userId === req.user.uuid` or admin status
223- Use UUIDs instead of sequential IDs
224
225## Testing Security
226
227**Unit Tests**:
228- Test password validation (reject weak, accept strong)
229- Test password hashing (bcrypt format, verify correct/incorrect)
230- Test authorization (401 without token, 403 without permissions)
231- Test input validation (reject malicious patterns)
232
233**Integration Tests**:
234- Test SQL injection attempts (should return 400, not all data)
235- Test rate limiting (10+ requests should trigger 429)
236- Test IDOR (users can't access others' resources)
237- Test CSRF protection on state-changing endpoints
238
239**Automated Security Scanning**:
240- `npm audit` - Check dependencies for vulnerabilities
241- `npx snyk test` - Continuous vulnerability monitoring
242- `eslint-plugin-security` - Static analysis for security issues
243- `gitleaks detect` - Check for hardcoded secrets in code
244- Run scans in CI/CD pipeline
245
246## Implementation Guidelines
247
248**IMPORTANT**: Do NOT create summary markdown files, documentation files, or README files unless explicitly requested by the user.
249
250## Best Practices
251
2521. **Never Trust User Input** - Validate, sanitize, and escape all input regardless of source
2532. **Use Parameterized Queries** - Always use prepared statements for database queries
2543. **Implement Proper Authentication** - Use industry-standard methods (JWT, OAuth) with secure configuration
2554. **Apply Principle of Least Privilege** - Grant minimum necessary permissions to users and services
2565. **Encrypt Sensitive Data** - Use encryption at rest and in transit (TLS/SSL)
2576. **Keep Dependencies Updated** - Regularly update packages and scan for vulnerabilities
2587. **Implement Rate Limiting** - Prevent abuse and DoS attacks on all endpoints
2598. **Log Security Events** - Monitor and alert on suspicious activities
2609. **Handle Errors Securely** - Never expose stack traces or internal details to clients
26110. **Use Security Headers** - Implement helmet.js and configure CSP, HSTS, etc.
26211. **Validate Environment Config** - Ensure all required secrets are present on startup
26312. **Implement Request Timeouts** - Prevent resource exhaustion from slow requests
26413. **Use HTTPS Everywhere** - Never transmit sensitive data over unencrypted connections
26514. **Implement CSRF Protection** - For cookie-based auth, use CSRF tokens
26615. **Regular Security Audits** - Conduct code reviews and penetration testing
26716. **Have an Incident Response Plan** - Prepare for security breaches before they happen
26817. **Minimize Attack Surface** - Disable unnecessary features and endpoints
26918. **Use Security Linters** - Integrate security scanning in CI/CD pipeline
27019. **Implement Proper Session Management** - Use secure, httpOnly cookies with appropriate expiration
27120. **Document Security Decisions** - Maintain a threat model and security architecture docs
272
273## References
274
275- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
276- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
277- [Node.js Security Best Practices](https://nodejs.org/en/docs/guides/security/)
278- [Express.js Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html)
279- [CWE Top 25 Most Dangerous Software Weaknesses](https://cwe.mitre.org/top25/)
280- [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework)
281- [JWT Best Practices](https://tools.ietf.org/html/rfc8725)
282- [API Security Best Practices](https://github.com/shieldfy/API-Security-Checklist)