Security Best Practices Checklist
A comprehensive security checklist for React Starter Kit applications. Review this checklist during development, before deployment, and regularly in production.
Development Phase
Code Security
Input Validation
- [ ] Validate all user inputs on both client and server
- [ ] Use Zod schemas for type-safe validation
- [ ] Sanitize HTML content to prevent XSS
- [ ] Validate file uploads (type, size, content)
- [ ] Implement rate limiting on forms and APIs
typescript
// Example: tRPC input validation with Zod
export const userRouter = router({
create: publicProcedure
.input(
z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
age: z.number().int().positive().max(120),
}),
)
.mutation(async ({ input }) => {
// Input is already validated
}),
});Authentication & Authorization
- [ ] Use Better Auth for authentication
- [ ] Implement proper session management
- [ ] Use secure session storage (httpOnly cookies)
- [ ] Implement CSRF protection
- [ ] Check permissions on every protected route
- [ ] Log authentication events
typescript
// Example: Protected tRPC procedure
export const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({ ctx: { ...ctx, user: ctx.session.user } });
});Data Protection
- [ ] Never log sensitive data (passwords, tokens, PII)
- [ ] Use parameterized queries (Drizzle ORM)
- [ ] Encrypt sensitive data at rest
- [ ] Implement proper error handling without data leaks
- [ ] Use HTTPS for all communications
- [ ] Validate and sanitize database queries
typescript
// Example: Safe database query with Drizzle
const users = await db
.select()
.from(usersTable)
.where(eq(usersTable.email, email)); // Parameterized, prevents SQL injectionSecret Management
Environment Variables
- [ ] Store secrets in
.env.local(never commit) - [ ] Use
.envonly for non-sensitive defaults - [ ] Document required variables in
.env - [ ] Validate environment variables at startup
- [ ] Use different secrets for each environment
typescript
// Example: Environment validation
const env = z
.object({
DATABASE_URL: z.string().url(),
JWT_SECRET: z.string().min(32),
SMTP_PASSWORD: z.string(),
PUBLIC_API_URL: z.string().url(), // Safe for client
})
.parse(process.env);Production Secrets
- [ ] Use Cloudflare Workers secrets for production
- [ ] Rotate secrets regularly
- [ ] Never hardcode secrets in code
- [ ] Audit secret access logs
- [ ] Use secret scanning in CI/CD
Dependencies
Package Management
- [ ] Run
bun auditregularly - [ ] Review new dependencies before adding
- [ ] Check dependency licenses
- [ ] Enable Dependabot alerts
- [ ] Keep dependencies up to date
- [ ] Use lock files (
bun.lockb)
bash
# Security audit commands
bun audit # Check for vulnerabilities
bun update --latest # Update dependencies
bun pm ls # List all dependenciesSupply Chain Security
- [ ] Verify package authenticity
- [ ] Use specific versions (not wildcards)
- [ ] Review dependency source code for critical packages
- [ ] Monitor for dependency hijacking
- [ ] Use SubResource Integrity (SRI) for CDN resources
Pre-Deployment Phase
Security Headers
Configure Headers
- [ ] Content Security Policy (CSP)
- [ ] X-Frame-Options
- [ ] X-Content-Type-Options
- [ ] Strict-Transport-Security (HSTS)
- [ ] Referrer-Policy
- [ ] Permissions-Policy
typescript
// Example: Security headers in Hono
app.use("*", async (c, next) => {
await next();
c.header("X-Frame-Options", "DENY");
c.header("X-Content-Type-Options", "nosniff");
c.header("Strict-Transport-Security", "max-age=31536000");
c.header("Content-Security-Policy", "default-src 'self'");
});API Security
tRPC Security
- [ ] Validate all inputs with Zod
- [ ] Implement rate limiting
- [ ] Use proper error codes
- [ ] Don't expose internal errors
- [ ] Log suspicious activities
- [ ] Implement request timeouts
typescript
// Example: Rate limiting middleware
const rateLimiter = new Map();
export const rateLimit = middleware(async ({ ctx, next }) => {
const key = ctx.ip;
const limit = rateLimiter.get(key) || 0;
if (limit > 10) {
throw new TRPCError({ code: "TOO_MANY_REQUESTS" });
}
rateLimiter.set(key, limit + 1);
setTimeout(() => rateLimiter.delete(key), 60000);
return next();
});CORS Configuration
- [ ] Configure allowed origins explicitly
- [ ] Don't use wildcard (*) in production
- [ ] Validate Origin header
- [ ] Configure allowed methods and headers
- [ ] Use credentials carefully
Client Security
React Security
- [ ] Avoid dangerouslySetInnerHTML
- [ ] Sanitize user-generated content
- [ ] Use Content Security Policy
- [ ] Validate URLs before navigation
- [ ] Implement proper error boundaries
- [ ] Don't expose sensitive data in state
typescript
// Example: Safe HTML rendering
import DOMPurify from 'isomorphic-dompurify'
function SafeHTML({ content }: { content: string }) {
const sanitized = DOMPurify.sanitize(content)
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />
}Browser Storage
- [ ] Don't store sensitive data in localStorage
- [ ] Use httpOnly cookies for sessions
- [ ] Encrypt sensitive client-side data
- [ ] Clear storage on logout
- [ ] Implement storage quotas
Deployment Phase
Infrastructure Security
Cloudflare Workers
- [ ] Configure WAF rules
- [ ] Enable DDoS protection
- [ ] Set up rate limiting
- [ ] Configure security headers
- [ ] Enable bot protection
- [ ] Monitor security events
toml
# Example: wrangler.toml security config
[env.production]
compatibility_date = "2024-01-01"
compatibility_flags = ["nodejs_compat"]
[env.production.rate_limiting]
enabled = true
requests_per_minute = 60CI/CD Security
- [ ] Use least privilege for CI/CD tokens
- [ ] Store secrets securely (GitHub Secrets)
- [ ] Enable branch protection
- [ ] Require code reviews
- [ ] Run security checks in pipeline
- [ ] Sign commits and releases
yaml
# Example: GitHub Actions security
- name: Run security audit
run: |
bun audit
bun test:security
- name: SAST Scan
uses: github/super-linter@v5
env:
VALIDATE_JAVASCRIPT_ES: true
VALIDATE_TYPESCRIPT_ES: trueMonitoring & Logging
Security Monitoring
- [ ] Log authentication attempts
- [ ] Monitor for suspicious patterns
- [ ] Set up security alerts
- [ ] Track rate limit violations
- [ ] Monitor dependency vulnerabilities
- [ ] Review logs regularly
typescript
// Example: Security event logging
function logSecurityEvent(event: {
type: string;
user?: string;
ip: string;
details: Record<string, any>;
}) {
console.log(
JSON.stringify({
timestamp: new Date().toISOString(),
severity: "SECURITY",
...event,
}),
);
}Incident Response
- [ ] Have incident response plan ready
- [ ] Configure security notifications
- [ ] Set up backup and recovery
- [ ] Document security contacts
- [ ] Test incident procedures
- [ ] Keep security playbook updated
Production Phase
Ongoing Security
Regular Tasks
- [ ] Weekly: Review security alerts
- [ ] Monthly: Run dependency audits
- [ ] Quarterly: Security assessment
- [ ] Annually: Penetration testing
- [ ] Ongoing: Security training
Security Updates
- [ ] Monitor security advisories
- [ ] Apply patches promptly
- [ ] Test updates in staging
- [ ] Document security changes
- [ ] Communicate with users about security
Compliance
Data Protection
- [ ] Implement GDPR compliance (if applicable)
- [ ] Add privacy policy
- [ ] Implement data deletion
- [ ] Log data access
- [ ] Encrypt personal data
Security Documentation
- [ ] Maintain SECURITY.md
- [ ] Document security procedures
- [ ] Keep incident log
- [ ] Update security checklist
- [ ] Train team on security
Quick Security Wins
For immediate security improvements:
Run Security Audit
bashbun auditAdd Security Headers
typescript// apps/api/src/index.ts app.use(securityHeaders());Implement Rate Limiting
typescript// apps/api/src/middleware.ts app.use(rateLimit({ limit: 100, window: "1m" }));Enable HTTPS Redirect
typescript// apps/web/src/index.ts if (location.protocol === "http:") { location.replace("https:" + window.location.href.substring(5)); }Add Input Validation
typescript// Use Zod everywhere const schema = z.object({ /* ... */ }); const validated = schema.parse(input);
Security Resources
Tools
- OWASP ZAP - Security scanning
- Snyk - Dependency scanning
- GitHub Security - Security features
- Mozilla Observatory - Security assessment
Documentation
Emergency Contacts
- Security Issues:
[email protected] - GitHub Security: Security Advisories
- CVE Database: MITRE CVE
Review this checklist regularly and update based on new threats and best practices.