Files
pos-system/.agent/rules/security.md

306 lines
8.9 KiB
Markdown

---
trigger: always_on
---
# Security Patterns for GoodGo Microservices
## When to Use This Skill
Use this skill when:
- Implementing authentication and authorization in any service
- Protecting sensitive data (PII, credentials, tokens)
- Validating user inputs and file uploads
- Implementing rate limiting and DDoS protection
- Setting up audit logging and security monitoring
- Encrypting data at rest and in transit
- Managing secrets and credentials
- Implementing security testing
- Handling security incidents
- Designing secure API endpoints
## Core Security Principles
1. **Defense in Depth**: Multiple layers of security controls
2. **Least Privilege**: Grant minimum required permissions
3. **Fail Secure**: Default to deny access
4. **Separation of Duties**: Critical operations require multiple approvals
5. **Audit Everything**: Log all security-relevant events
6. **Encrypt Sensitive Data**: PII, tokens, credentials must be encrypted
7. **Validate All Inputs**: Never trust user input
8. **Principle of Least Exposure**: Minimize attack surface
9. **Secure by Default**: Security built-in, not bolted on
10. **Assume Breach**: Design for detection and response
## Authentication & Authorization
### JWT Token Validation
Extract tokens from Authorization header or cookies, verify with `jwtService.verifyAccessToken()`, and attach user payload to request. Return 401 for missing/invalid tokens.
```typescript
// Key pattern - see references/REFERENCE.md for full implementation
const authHeader = req.headers.authorization;
const token = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : req.cookies?.access_token;
const payload = await jwtService.verifyAccessToken(token);
req.user = { id: payload.sub, roles: payload.roles || [], permissions: payload.permissions || [] };
```
### Role-Based Authorization (RBAC)
Use `requireRole()` middleware for role checks and `requirePermission()` for fine-grained access control with `resource:action` format.
```typescript
// Usage pattern
router.post('/api/v1/users', authenticate(), requirePermission('users', 'create'), userController.create);
router.delete('/api/v1/admin', authenticate(), requireRole('admin', 'superadmin'), adminController.delete);
```
### Resource Ownership
Validate users can only access their own resources using `requireOwnership()` middleware.
## Data Protection
### Encryption
- Use AES-256-GCM for encrypting PII at rest
- Store encrypted data as `iv:tag:ciphertext` format
- Require 32+ character ENCRYPTION_KEY
### Password Hashing
- Always use bcrypt with cost factor 12 in production
- Never log passwords - sanitize before logging
### Token Storage
- Hash tokens with SHA-256 before database storage
- Use `crypto.randomBytes(32)` for secure token generation
## Input Validation
### Zod Schema Validation
Always validate inputs with Zod schemas before processing:
```typescript
const CreateUserDto = z.object({
email: z.string().email(),
password: z.string().min(8).regex(/[A-Z]/).regex(/[a-z]/).regex(/[0-9]/).regex(/[^A-Za-z0-9]/),
phone: z.string().regex(/^\+[1-9]\d{1,14}$/).optional(),
name: z.string().min(1).max(255)
});
// In controller
const dto = CreateUserDto.parse(req.body);
```
### File Upload Validation
- Check file size (max 10MB default)
- Validate MIME type against whitelist
- Verify content with `file-type` library to prevent MIME spoofing
### SQL Injection Prevention
Always use Prisma parameterized queries - never string concatenation for queries.
## Rate Limiting
Configure Redis-backed rate limiting for all endpoints:
| Limiter Type | Window | Max Requests | Use Case |
|-------------|--------|--------------|----------|
| Standard | 15 min | 100 | General API endpoints |
| Strict | 1 hour | 10 | Sensitive operations |
| Login | 15 min | 5 | Authentication endpoints |
```typescript
router.post('/api/v1/auth/login', loginLimiter, authController.login);
```
## Security Headers
Use Helmet middleware with CSP, HSTS, and additional headers:
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `X-XSS-Protection: 1; mode=block`
- `Referrer-Policy: strict-origin-when-cross-origin`
## CORS Configuration
- Whitelist allowed origins from environment variables
- Enable credentials for authenticated requests
- Set `maxAge: 86400` (24 hours) for preflight caching
## Secrets Management
- Never hardcode secrets - use environment variables
- Validate secrets with Zod schema at startup
- Use secret managers in production (AWS Secrets Manager, Vault, etc.)
- Rotate secrets quarterly
```typescript
const secretsSchema = z.object({
JWT_SECRET: z.string().min(32),
DATABASE_URL: z.string().url(),
ENCRYPTION_KEY: z.string().min(32).optional()
});
```
## Audit Logging
Log all security-relevant events with sanitized details:
```typescript
await auditService.logSecurityEvent('LOGIN_SUCCESS', user.id, { email: user.email }, req);
await auditService.logSecurityEvent('PERMISSION_DENIED', user.id, { resource, action }, req);
```
Sanitize sensitive fields: password, token, secret, ssn, creditCard.
## Error Handling
- Log full errors internally
- Never expose user existence (use generic "Invalid credentials")
- Show stack traces only in development
- Return sanitized error codes in production
## Security Testing
Write tests for:
- SQL injection prevention
- XSS attack prevention
- Authentication enforcement
- Authorization enforcement
- Rate limiting effectiveness
## Best Practices
- All endpoints require authentication (except public)
- Authorization checks at every protected route
- Input validation with Zod on all user input
- Rate limiting on all endpoints
- Error messages sanitized in production
- PII encrypted at rest with AES-256-GCM
- Passwords hashed with bcrypt (cost 12+)
- Tokens hashed before database storage
- HTTPS enforced (TLS 1.2+)
- Security headers via Helmet
- Audit logging for security events
- Dependencies scanned for vulnerabilities
- File uploads validated (size, type, content)
## Common Mistakes
### 1. Weak Password Hashing
```typescript
// BAD: Low cost factor
const hash = await bcrypt.hash(password, 8);
// GOOD: Use cost 12
const hash = await bcrypt.hash(password, 12);
```
### 2. Hardcoded Secrets
```typescript
// BAD
const JWT_SECRET = "my-secret-key";
// GOOD
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) throw new Error('JWT_SECRET required');
```
### 3. Missing Input Validation
```typescript
// BAD
const user = await prisma.user.findUnique({ where: { id: req.params.id } });
// GOOD
const { id } = z.object({ id: z.string().cuid() }).parse(req.params);
const user = await prisma.user.findUnique({ where: { id } });
```
### 4. Logging Sensitive Data
```typescript
// BAD
logger.info('User login', { email, password });
// GOOD
logger.info('User login', { email, password: '[REDACTED]' });
```
### 5. Exposing User Existence
```typescript
// BAD
if (!user) throw new Error('User not found');
// GOOD
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
throw new Error('Invalid credentials');
}
```
## Quick Reference
| Security Area | Implementation |
|--------------|----------------|
| **Password hashing** | `bcrypt.hash(password, 12)` |
| **JWT Access Token** | 15 minutes expiry |
| **JWT Refresh Token** | 7 days expiry |
| **Rate limiting** | Standard: 100/15min, Strict: 10/hour, Login: 5/15min |
| **Encryption** | AES-256-GCM for PII |
| **Input validation** | Zod schemas, always parse before use |
| **SQL injection** | Use Prisma (parameterized by default) |
| **Security headers** | helmet middleware |
| **CORS** | Whitelist origins, credentials: true |
**Essential Imports:**
```typescript
import bcrypt from 'bcrypt';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { z } from 'zod';
import { jwtService } from '@goodgo/auth-sdk';
```
## Security Checklist
Before deploying any service:
- [ ] All endpoints require authentication (except public)
- [ ] Authorization checks implemented (RBAC/ABAC)
- [ ] Input validation with Zod schemas
- [ ] Rate limiting configured
- [ ] Error messages sanitized (no info disclosure)
- [ ] PII encrypted at rest
- [ ] Passwords hashed with bcrypt (cost 12+)
- [ ] Tokens hashed before storing
- [ ] Secrets in environment variables (never hardcoded)
- [ ] HTTPS enforced (TLS 1.2+)
- [ ] CORS configured correctly
- [ ] Security headers set (helmet)
- [ ] Audit logging enabled
- [ ] SQL injection prevented (use Prisma)
- [ ] XSS prevention (input sanitization)
- [ ] File upload validation
- [ ] Security tests passing
- [ ] Dependencies scanned for vulnerabilities
- [ ] Secrets rotation plan in place
## Resources
- [Detailed Code Examples](./references/REFERENCE.md) - Full implementation examples
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/)
- [Node.js Security Best Practices](https://nodejs.org/en/docs/guides/security/)
- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html)