250 lines
6.5 KiB
Markdown
250 lines
6.5 KiB
Markdown
# Security & Architecture Improvements
|
|
|
|
## 🔒 Current Security Issues
|
|
|
|
### 1. API Key Exposure in Frontend
|
|
**Issue**: EmailSender component stores API key in browser state
|
|
```typescript
|
|
// CURRENT - INSECURE
|
|
const [apiKey, setApiKey] = useState('') // Exposed in browser
|
|
```
|
|
|
|
**Fix**: Remove frontend API key input entirely
|
|
```typescript
|
|
// RECOMMENDED - Remove EmailSender from production
|
|
// Only use for development testing
|
|
```
|
|
|
|
### 2. Missing Input Validation
|
|
**Issue**: No validation for email addresses, URLs, or data inputs
|
|
```typescript
|
|
// CURRENT - NO VALIDATION
|
|
const handleSendEmail = async () => {
|
|
// Direct use without validation
|
|
}
|
|
```
|
|
|
|
**Fix**: Add proper validation
|
|
```typescript
|
|
// RECOMMENDED
|
|
import { z } from 'zod'
|
|
|
|
const emailSchema = z.object({
|
|
to: z.string().email(),
|
|
eventName: z.string().min(1).max(200),
|
|
ctaUrl: z.string().url()
|
|
})
|
|
|
|
const validateInput = (data: unknown) => {
|
|
return emailSchema.parse(data)
|
|
}
|
|
```
|
|
|
|
### 3. Missing Rate Limiting
|
|
**Issue**: No protection against email spam/abuse
|
|
```typescript
|
|
// CURRENT - NO RATE LIMITING
|
|
await resend.emails.send(payload)
|
|
```
|
|
|
|
**Fix**: Implement rate limiting
|
|
```typescript
|
|
// RECOMMENDED
|
|
import rateLimit from 'express-rate-limit'
|
|
|
|
const emailLimiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 10, // limit each IP to 10 emails per windowMs
|
|
message: 'Too many emails sent, please try again later'
|
|
})
|
|
|
|
app.use('/api/send-email', emailLimiter)
|
|
```
|
|
|
|
### 4. Missing Environment Variables
|
|
**Issue**: No .env file or environment configuration
|
|
```bash
|
|
# MISSING
|
|
RESEND_API_KEY=
|
|
FROM_DOMAIN=
|
|
RATE_LIMIT_MAX=
|
|
```
|
|
|
|
**Fix**: Add environment configuration
|
|
```bash
|
|
# .env
|
|
RESEND_API_KEY=re_your_key_here
|
|
FROM_DOMAIN=yourdomain.com
|
|
RATE_LIMIT_MAX=10
|
|
RATE_LIMIT_WINDOW_MS=900000
|
|
```
|
|
|
|
### 5. Missing Content Security Policy
|
|
**Issue**: No CSP headers for XSS protection
|
|
```typescript
|
|
// RECOMMENDED - Add to backend
|
|
app.use((req, res, next) => {
|
|
res.setHeader('Content-Security-Policy',
|
|
"default-src 'self'; script-src 'none'; object-src 'none';"
|
|
)
|
|
next()
|
|
})
|
|
```
|
|
|
|
## 🏗️ Architecture Improvements
|
|
|
|
### 1. Add Environment Configuration
|
|
```typescript
|
|
// config/email.ts
|
|
export const emailConfig = {
|
|
resend: {
|
|
apiKey: process.env.RESEND_API_KEY!,
|
|
fromDomain: process.env.FROM_DOMAIN!,
|
|
},
|
|
rateLimit: {
|
|
max: parseInt(process.env.RATE_LIMIT_MAX || '10'),
|
|
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000'),
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Add Input Validation Layer
|
|
```typescript
|
|
// lib/validation.ts
|
|
import { z } from 'zod'
|
|
|
|
export const invitationSchema = z.object({
|
|
to: z.string().email(),
|
|
eventName: z.string().min(1).max(200),
|
|
dateTime: z.string().min(1),
|
|
location: z.string().min(1).max(500),
|
|
ctaUrl: z.string().url(),
|
|
})
|
|
|
|
export const paymentSchema = z.object({
|
|
to: z.string().email(),
|
|
amount: z.number().positive(),
|
|
currency: z.enum(['USD', 'EUR', 'GBP']),
|
|
description: z.string().min(1).max(500),
|
|
})
|
|
```
|
|
|
|
### 3. Add Logging & Monitoring
|
|
```typescript
|
|
// lib/logger.ts
|
|
export const logger = {
|
|
info: (message: string, meta?: any) => {
|
|
console.log(JSON.stringify({ level: 'info', message, meta, timestamp: new Date() }))
|
|
},
|
|
error: (message: string, error?: any) => {
|
|
console.error(JSON.stringify({ level: 'error', message, error: error?.message, timestamp: new Date() }))
|
|
}
|
|
}
|
|
|
|
// Usage in ResendService
|
|
async sendEmail(...) {
|
|
try {
|
|
logger.info('Sending email', { templateId, to })
|
|
const result = await this.resend.emails.send(payload)
|
|
logger.info('Email sent successfully', { messageId: result.data?.id })
|
|
return result
|
|
} catch (error) {
|
|
logger.error('Failed to send email', error)
|
|
throw error
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. Add Error Handling Middleware
|
|
```typescript
|
|
// middleware/errorHandler.ts
|
|
export const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => {
|
|
logger.error('Unhandled error', err)
|
|
|
|
if (err.name === 'ValidationError') {
|
|
return res.status(400).json({ error: 'Invalid input data' })
|
|
}
|
|
|
|
if (err.message.includes('Resend')) {
|
|
return res.status(503).json({ error: 'Email service temporarily unavailable' })
|
|
}
|
|
|
|
res.status(500).json({ error: 'Internal server error' })
|
|
}
|
|
```
|
|
|
|
## 🛡️ Production Security Checklist
|
|
|
|
### Backend Security
|
|
- [ ] Remove EmailSender component from production build
|
|
- [ ] Add input validation with Zod or similar
|
|
- [ ] Implement rate limiting
|
|
- [ ] Add proper error handling
|
|
- [ ] Use environment variables for all secrets
|
|
- [ ] Add request logging
|
|
- [ ] Implement CORS properly
|
|
- [ ] Add Content Security Policy headers
|
|
- [ ] Validate email addresses before sending
|
|
- [ ] Sanitize all user inputs
|
|
|
|
### Email Security
|
|
- [ ] Validate all URLs before including in emails
|
|
- [ ] Use only verified domains for sending
|
|
- [ ] Implement unsubscribe links where required
|
|
- [ ] Add SPF, DKIM, DMARC records
|
|
- [ ] Monitor bounce rates and spam reports
|
|
- [ ] Implement email delivery tracking
|
|
|
|
### Infrastructure Security
|
|
- [ ] Use HTTPS only
|
|
- [ ] Implement proper authentication
|
|
- [ ] Add API key rotation
|
|
- [ ] Monitor API usage
|
|
- [ ] Set up alerts for unusual activity
|
|
- [ ] Regular security audits
|
|
|
|
## 📋 Recommended File Structure
|
|
|
|
```
|
|
backend/
|
|
├── src/
|
|
│ ├── config/
|
|
│ │ ├── email.ts # Email configuration
|
|
│ │ └── security.ts # Security settings
|
|
│ ├── middleware/
|
|
│ │ ├── auth.ts # Authentication
|
|
│ │ ├── rateLimit.ts # Rate limiting
|
|
│ │ └── validation.ts # Input validation
|
|
│ ├── services/
|
|
│ │ ├── emailService.ts # Email sending logic
|
|
│ │ └── templateService.ts # Template management
|
|
│ ├── templates/ # Email templates (copied from playground)
|
|
│ ├── utils/
|
|
│ │ ├── logger.ts # Logging utility
|
|
│ │ └── validator.ts # Validation schemas
|
|
│ └── routes/
|
|
│ └── emails.ts # Email API routes
|
|
├── .env # Environment variables
|
|
├── .env.example # Environment template
|
|
└── package.json
|
|
```
|
|
|
|
## 🚀 Implementation Priority
|
|
|
|
1. **High Priority** (Security Critical)
|
|
- Remove API key from frontend
|
|
- Add input validation
|
|
- Implement rate limiting
|
|
- Add environment variables
|
|
|
|
2. **Medium Priority** (Best Practices)
|
|
- Add proper error handling
|
|
- Implement logging
|
|
- Add CORS configuration
|
|
- Content Security Policy
|
|
|
|
3. **Low Priority** (Nice to Have)
|
|
- Email delivery tracking
|
|
- Advanced monitoring
|
|
- Performance optimization
|
|
- A/B testing framework |