Overview of ShipSafe's comprehensive 7-layer security architecture.
Overview
ShipSafe implements a multi-layered security architecture designed to protect your application from common threats and vulnerabilities. All security features are enabled by default and work together to provide defense-in-depth.
Security Layers:
- HTTPS Enforcement - All traffic encrypted in production
- Rate Limiting - Prevents abuse and brute force attacks
- API Firewall - Blocks invalid requests before they reach your code
- CSRF Protection - Prevents cross-site request forgery
- Security Headers - Strong HTTP security headers
- Audit Logging - Security event tracking
- Authentication Middleware - Protected route verification
Security Architecture
Layer 1: HTTPS Enforcement
Purpose: Encrypts all traffic between client and server.
Implementation:
- Automatically redirects HTTP to HTTPS in production
- Enforces secure connections
- Prevents man-in-the-middle attacks
Location: src/lib/security/env.ts
// Middleware automatically enforces HTTPS
if (process.env.NODE_ENV === "production") {
// Redirect HTTP to HTTPS
}
Layer 2: Rate Limiting
Purpose: Prevents abuse, brute force attacks, and DDoS.
Implementation:
- Per-IP rate limiting
- Per-endpoint rate limiting
- Sliding window algorithm
- Configurable limits
Location: src/lib/security/rate_limit.ts
Default Limits:
- Auth endpoints: 10 requests per 15 minutes per IP
- API endpoints: 100 requests per 15 minutes per IP
- Webhooks: 1000 requests per hour per IP
Customization:
// In rate_limit.ts
const RATE_LIMITS = {
"/api/auth/login": { requests: 5, window: 15 * 60 }, // 5 per 15 min
"/api/auth/signup": { requests: 3, window: 60 * 60 }, // 3 per hour
};
Layer 3: API Firewall
Purpose: Blocks invalid requests before they reach your route handlers.
Checks:
- Valid HTTP methods only (GET, POST, PUT, PATCH, DELETE)
- Valid user agents (blocks bots and automated tools)
- Valid content-type headers
- Origin/referrer validation (optional)
Location: src/lib/security/secure_api.ts
Allowed User Agents:
- Browser user agents (Mozilla, Chrome, Safari, etc.)
- Next.js SSR user agent
- Stripe webhook user agent
- Firebase SDK user agent
Blocked:
- Empty or missing user agents
- Suspicious user agents
- Invalid HTTP methods (HEAD, OPTIONS, TRACE, etc.)
Layer 4: CSRF Protection
Purpose: Prevents cross-site request forgery attacks.
Implementation:
- Double-submit cookie pattern
- CSRF token validation
- Automatic token generation and validation
How it works:
- Server generates CSRF token and sets cookie
- Client includes token in request header
- Server validates token matches cookie
Usage:
// Client automatically includes CSRF token
const response = await apiPost("/api/endpoint", data);
// Server validates automatically via middleware
Layer 5: Security Headers
Purpose: Sets strong HTTP security headers.
Headers:
Strict-Transport-Security- Enforces HTTPSX-Frame-Options: DENY- Prevents clickjackingX-Content-Type-Options: nosniff- Prevents MIME sniffingReferrer-Policy: strict-origin-when-cross-originContent-Security-Policy- XSS protection (optional)
Implementation:
// Middleware automatically sets headers
export function middleware(request: NextRequest) {
const response = NextResponse.next();
response.headers.set("X-Frame-Options", "DENY");
response.headers.set("X-Content-Type-Options", "nosniff");
// ... more headers
return response;
}
Layer 6: Audit Logging
Purpose: Tracks security events for monitoring and debugging.
Logged Events:
- Failed authentication attempts
- Rate limit violations
- Security header violations
- Suspicious requests
Location: src/lib/security/audit.ts
Usage:
import { logSecurityEvent } from "@/lib/security/audit";
logSecurityEvent(req, "RATE_LIMIT_EXCEEDED", "Too many requests from IP");
logSecurityEvent(req, "AUTH_FAILED", "Invalid credentials");
Layer 7: Authentication Middleware
Purpose: Verifies authentication for protected routes.
Implementation:
- Firebase ID token verification
- Custom claims validation
- Role-based access control
Usage:
// In API routes
import { requireAuth } from "@/lib/firebase/auth";
export async function GET(req: NextRequest) {
const user = await requireAuth(req); // Throws if not authenticated
// Protected code here
}
Security Features by Route Type
Public Routes
Protection:
- HTTPS enforcement
- Rate limiting
- API firewall
- Security headers
No protection:
- Authentication (public access)
- CSRF (read-only operations)
Protected Routes
Protection:
- All public protections
- Authentication required
- CSRF protection
- Role-based access control
Example:
export async function POST(req: NextRequest) {
// All security layers applied automatically
const user = await requireAuth(req); // Layer 7
// ... your code
}
Webhook Routes
Protection:
- Signature verification (Stripe, etc.)
- Rate limiting
- API firewall
- HTTPS enforcement
No protection:
- CSRF (webhooks don't use cookies)
- Authentication (uses signature instead)
Input Validation
Zod Schema Validation
All inputs are validated using Zod schemas:
import { z } from "zod";
import { loginSchema } from "@/features/auth/schema";
export async function POST(req: NextRequest) {
const body = await req.json();
const data = loginSchema.parse(body); // Validates and sanitizes
}
Security Benefits:
- Type safety
- Input sanitization
- Injection attack prevention
- Data normalization
Environment Security
Secure Environment Variable Access
Location: src/lib/security/env.ts
Features:
- Validates required environment variables
- Provides helpful error messages
- Prevents accidental exposure
import { getEnv } from "@/lib/security/env";
// Throws if not set
const apiKey = getEnv("STRIPE_SECRET_KEY");
// With fallback
const apiKey = getEnv("STRIPE_SECRET_KEY", "fallback-value");
Environment Variable Validation
// Validates on app startup
function validateEnvironment() {
const required = [
"FIREBASE_PROJECT_ID",
"STRIPE_SECRET_KEY",
// ... more
];
required.forEach(key => {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
});
}
Security Best Practices
1. Never Trust Client Input
// ✅ Good: Validate all inputs
const data = schema.parse(req.body);
// ❌ Bad: Trust client data
const email = req.body.email; // Don't do this
2. Use Parameterized Queries
// ✅ Good: Firestore handles this automatically
await firestore.collection("users").doc(userId).get();
// ❌ Bad: SQL injection (not applicable to Firestore, but good practice)
3. Sanitize Output
// ✅ Good: Escape user input
<div>{escapeHtml(user.displayName)}</div>
// React automatically escapes, but be careful with dangerouslySetInnerHTML
4. Use HTTPS Everywhere
// ✅ Good: Always use HTTPS in production
const url = `https://${config.domainName}/api/endpoint`;
5. Log Security Events
// ✅ Good: Log suspicious activity
logSecurityEvent(req, "SUSPICIOUS_REQUEST", "Invalid user agent");
Security Monitoring
Audit Log Review
import { getAuditLogs } from "@/lib/security/audit";
// Get recent security events
const logs = getAuditLogs(100);
// Filter for specific events
const failedLogins = logs.filter(log => log.type === "AUTH_FAILED");
Rate Limit Monitoring
Monitor rate limit violations to detect abuse:
const rateLimitLogs = getAuditLogs(1000).filter(
log => log.type === "RATE_LIMIT_EXCEEDED"
);
Common Security Threats
1. Brute Force Attacks
Protection: Rate limiting on auth endpoints
// Limits login attempts to 5 per 15 minutes
RATE_LIMITS["/api/auth/login"] = {
requests: 5,
window: 15 * 60,
};
2. SQL Injection
Protection: Not applicable (Firestore uses NoSQL), but good practices still apply
3. XSS Attacks
Protection:
- React automatically escapes
- Content Security Policy headers
- Input validation
4. CSRF Attacks
Protection: Double-submit cookie pattern
5. DDoS Attacks
Protection:
- Rate limiting
- API firewall
- CDN (Vercel/Cloudflare)
Security Checklist
- ✅ HTTPS enforced in production
- ✅ Rate limiting enabled
- ✅ API firewall active
- ✅ CSRF protection enabled
- ✅ Security headers set
- ✅ Audit logging configured
- ✅ Input validation on all endpoints
- ✅ Authentication on protected routes
- ✅ Environment variables secure
- ✅ Error messages don't leak sensitive info
Troubleshooting
Rate Limit False Positives
If legitimate users hit rate limits:
- Increase limits for specific endpoints
- Adjust window size
- Whitelist trusted IPs
CSRF Token Issues
If CSRF validation fails:
- Check cookies are enabled
- Verify token is sent in header
- Check domain/subdomain settings
Security Headers Blocking Content
If security headers block legitimate content:
- Adjust Content-Security-Policy
- Review X-Frame-Options settings
- Check CORS configuration
Learn More
- Security Overview - Detailed security documentation
- API Security - API route security
- Rate Limiting - Rate limit configuration
- CSRF Protection - CSRF implementation
- Security Headers - HTTP headers configuration