docs/security/checklist.md
A comprehensive security checklist for React Starter Kit applications. Review this checklist during development, before deployment, and regularly in production.
// 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
}),
});
// 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 } });
});
// Example: Safe database query with Drizzle
const users = await db
.select()
.from(usersTable)
.where(eq(usersTable.email, email)); // Parameterized, prevents SQL injection
.env.local (never commit).env only for non-sensitive defaults.env// 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);
bun audit regularlybun.lockb)# Security audit commands
bun audit # Check for vulnerabilities
bun update --latest # Update dependencies
bun pm ls # List all dependencies
// 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'");
});
// 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();
});
// Example: Safe HTML rendering
import DOMPurify from 'isomorphic-dompurify'
function SafeHTML({ content }: { content: string }) {
const sanitized = DOMPurify.sanitize(content)
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />
}
# 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 = 60
# 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: true
// 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,
}),
);
}
For immediate security improvements:
Run Security Audit
bun audit
Add Security Headers
// apps/api/src/index.ts
app.use(securityHeaders());
Implement Rate Limiting
// apps/api/src/middleware.ts
app.use(rateLimit({ limit: 100, window: "1m" }));
Enable HTTPS Redirect
// apps/web/src/index.ts
if (location.protocol === "http:") {
location.replace("https:" + window.location.href.substring(5));
}
Add Input Validation
// Use Zod everywhere
const schema = z.object({
/* ... */
});
const validated = schema.parse(input);
[email protected]Review this checklist regularly and update based on new threats and best practices.