Security Guidelines
Build secure applications with Orchestre by following these security best practices. Security should be integrated throughout development, not added as an afterthought.
Security-First Development
1. Use Security Commands
Orchestre provides specialized security commands:
bash
# Regular security audits
/security-audit
# Focused security reviews
/security-audit --focus authentication
/security-audit --compliance OWASP
# Validate fixes
/security-audit --validate-fixes2. Secure by Default
When generating code, Orchestre applies security best practices:
bash
# Authentication with security built-in
/setup-oauth
# Includes: CSRF protection, secure cookies, rate limiting
# API endpoints with validation
/add-api-endpoint "POST /api/users"
# Includes: Input validation, authentication checks, sanitizationAuthentication & Authorization
1. Strong Authentication
Password Security
typescript
// Orchestre generates secure password handling
import bcrypt from 'bcrypt'
const SALT_ROUNDS = 12 // Adaptive hashing
export async function hashPassword(password: string): Promise<string> {
// Validate password strength
if (!isStrongPassword(password)) {
throw new Error('Password does not meet requirements')
}
return bcrypt.hash(password, SALT_ROUNDS)
}
function isStrongPassword(password: string): boolean {
return (
password.length >= 8 &&
/[A-Z]/.test(password) && // Uppercase
/[a-z]/.test(password) && // Lowercase
/[0-9]/.test(password) && // Number
/[^A-Za-z0-9]/.test(password) // Special char
)
}Multi-Factor Authentication
bash
# Add MFA to your application
/setup-mfa "TOTP and SMS backup"Generated implementation:
typescript
// Time-based OTP
import { authenticator } from 'otplib'
export function setupMFA(userId: string) {
const secret = authenticator.generateSecret()
// Store encrypted secret
await db.users.update({
where: { id: userId },
data: {
mfaSecret: encrypt(secret),
mfaEnabled: false // Enable after verification
}
})
// Generate QR code
const otpauth = authenticator.keyuri(
user.email,
'YourApp',
secret
)
return { secret, qrCode: await generateQR(otpauth) }
}2. Authorization Patterns
Role-Based Access Control (RBAC)
typescript
// Middleware for route protection
export function requireRole(roles: string[]) {
return async (req: Request, res: Response, next: NextFunction) => {
const user = req.user
if (!user) {
return res.status(401).json({ error: 'Unauthorized' })
}
if (!roles.includes(user.role)) {
return res.status(403).json({ error: 'Forbidden' })
}
next()
}
}
// Usage
app.post('/api/admin/users',
authenticate,
requireRole(['admin']),
createUser
)Attribute-Based Access Control (ABAC)
typescript
// More flexible permission system
export class PermissionChecker {
async canAccess(
user: User,
resource: Resource,
action: Action
): Promise<boolean> {
// Check ownership
if (resource.ownerId === user.id) return true
// Check team membership
if (await this.isTeamMember(user.id, resource.teamId)) {
return this.teamPermissions[action]
}
// Check role permissions
return this.hasRolePermission(user.role, resource.type, action)
}
}Input Validation & Sanitization
1. Always Validate Input
typescript
// Use schema validation
import { z } from 'zod'
const CreateUserSchema = z.object({
email: z.string().email(),
password: z.string().min(8).max(128),
name: z.string().min(1).max(100).regex(/^[a-zA-Z\s'-]+$/),
age: z.number().min(13).max(120).optional()
})
export async function createUser(req: Request, res: Response) {
try {
const validated = CreateUserSchema.parse(req.body)
// Proceed with validated data
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({
error: 'Validation failed',
details: error.errors
})
}
}
}2. SQL Injection Prevention
typescript
// ❌ NEVER do this
const query = `SELECT * FROM users WHERE email = '${email}'`
// ✅ Use parameterized queries
// With Prisma
const user = await prisma.user.findUnique({
where: { email }
})
// With raw SQL
const user = await db.query(
'SELECT * FROM users WHERE email = $1',
[email]
)
// With query builders
const user = await db
.select()
.from('users')
.where('email', '=', email)
.first()3. XSS Prevention
typescript
// Sanitize user-generated content
import DOMPurify from 'isomorphic-dompurify'
export function sanitizeHTML(dirty: string): string {
return DOMPurify.sanitize(dirty, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href', 'target']
})
}
// React automatically escapes, but be careful with dangerouslySetInnerHTML
function UserContent({ html }: { html: string }) {
return (
<div
dangerouslySetInnerHTML={{
__html: sanitizeHTML(html)
}}
/>
)
}Data Protection
1. Encryption
At Rest
typescript
// Encrypt sensitive data before storage
import crypto from 'crypto'
const algorithm = 'aes-256-gcm'
export function encrypt(text: string, key: Buffer): EncryptedData {
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv(algorithm, key, iv)
let encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
const authTag = cipher.getAuthTag()
return {
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
}
}
export function decrypt(data: EncryptedData, key: Buffer): string {
const decipher = crypto.createDecipheriv(
algorithm,
key,
Buffer.from(data.iv, 'hex')
)
decipher.setAuthTag(Buffer.from(data.authTag, 'hex'))
let decrypted = decipher.update(data.encrypted, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}In Transit
typescript
// Force HTTPS
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
return res.redirect(`https://${req.header('host')}${req.url}`)
}
next()
})
// HSTS header
app.use((req, res, next) => {
res.setHeader(
'Strict-Transport-Security',
'max-age=31536000; includeSubDomains; preload'
)
next()
})2. Secure Headers
typescript
// Security headers middleware
import helmet from 'helmet'
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'", "'unsafe-eval'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}))API Security
1. Rate Limiting
typescript
// Prevent abuse with rate limiting
import rateLimit from 'express-rate-limit'
// General API limit
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests, please try again later'
})
// Strict limit for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
skipSuccessfulRequests: true
})
app.use('/api/', apiLimiter)
app.use('/api/auth/', authLimiter)2. API Key Management
typescript
// Secure API key generation and validation
export class APIKeyManager {
generateKey(): string {
// Generate cryptographically secure key
const key = crypto.randomBytes(32).toString('hex')
const hashedKey = this.hashKey(key)
// Store only the hash
await db.apiKeys.create({
key: hashedKey,
createdAt: new Date(),
lastUsed: null
})
// Return the key only once
return key
}
async validateKey(key: string): Promise<boolean> {
const hashedKey = this.hashKey(key)
const apiKey = await db.apiKeys.findUnique({
where: { key: hashedKey }
})
if (!apiKey) return false
// Update last used
await db.apiKeys.update({
where: { key: hashedKey },
data: { lastUsed: new Date() }
})
return true
}
private hashKey(key: string): string {
return crypto
.createHash('sha256')
.update(key)
.digest('hex')
}
}3. CORS Configuration
typescript
// Configure CORS properly
import cors from 'cors'
const corsOptions = {
origin: (origin, callback) => {
const allowedOrigins = [
'https://app.example.com',
'https://staging.example.com'
]
// Allow requests with no origin (mobile apps, Postman)
if (!origin) return callback(null, true)
if (allowedOrigins.includes(origin)) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
credentials: true, // Allow cookies
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
maxAge: 86400 // Cache preflight for 24 hours
}
app.use(cors(corsOptions))Session Security
1. Secure Session Configuration
typescript
// Express session security
import session from 'express-session'
app.use(session({
secret: process.env.SESSION_SECRET,
name: 'sessionId', // Don't use default name
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JS access
maxAge: 1000 * 60 * 60 * 24, // 24 hours
sameSite: 'strict' // CSRF protection
},
store: new RedisStore({
client: redisClient,
prefix: 'sess:'
})
}))2. JWT Security
typescript
// Secure JWT implementation
import jwt from 'jsonwebtoken'
export class TokenManager {
private readonly accessTokenExpiry = '15m'
private readonly refreshTokenExpiry = '7d'
generateTokenPair(userId: string) {
const accessToken = jwt.sign(
{ userId, type: 'access' },
process.env.JWT_ACCESS_SECRET,
{
expiresIn: this.accessTokenExpiry,
algorithm: 'RS256' // Use RSA for better security
}
)
const refreshToken = jwt.sign(
{ userId, type: 'refresh' },
process.env.JWT_REFRESH_SECRET,
{
expiresIn: this.refreshTokenExpiry,
algorithm: 'RS256'
}
)
return { accessToken, refreshToken }
}
verifyToken(token: string, type: 'access' | 'refresh') {
const secret = type === 'access'
? process.env.JWT_ACCESS_SECRET
: process.env.JWT_REFRESH_SECRET
try {
const payload = jwt.verify(token, secret, {
algorithms: ['RS256'] // Prevent algorithm switching attacks
})
if (payload.type !== type) {
throw new Error('Invalid token type')
}
return payload
} catch (error) {
throw new Error('Invalid token')
}
}
}Error Handling
1. Safe Error Messages
typescript
// Don't leak sensitive information
export function errorHandler(
err: Error,
req: Request,
res: Response,
next: NextFunction
) {
// Log full error internally
logger.error({
error: err.message,
stack: err.stack,
url: req.url,
method: req.method,
ip: req.ip,
userId: req.user?.id
})
// Send safe error to client
const isDev = process.env.NODE_ENV === 'development'
res.status(err.status || 500).json({
error: {
message: isDev ? err.message : 'An error occurred',
code: err.code || 'INTERNAL_ERROR',
...(isDev && { stack: err.stack })
}
})
}2. Audit Logging
typescript
// Log security-relevant events
export class AuditLogger {
async log(event: AuditEvent) {
await db.auditLogs.create({
type: event.type,
userId: event.userId,
ip: event.ip,
userAgent: event.userAgent,
action: event.action,
resource: event.resource,
result: event.result,
metadata: event.metadata,
timestamp: new Date()
})
// Alert on suspicious events
if (this.isSuspicious(event)) {
await this.alertSecurityTeam(event)
}
}
private isSuspicious(event: AuditEvent): boolean {
return (
event.type === 'MULTIPLE_FAILED_LOGINS' ||
event.type === 'PRIVILEGE_ESCALATION' ||
event.type === 'DATA_EXPORT' ||
event.result === 'UNAUTHORIZED'
)
}
}Security Testing
1. Automated Security Tests
typescript
// Security test suite
describe('Security', () => {
describe('Authentication', () => {
it('should prevent brute force attacks', async () => {
// Try 6 failed logins
for (let i = 0; i < 6; i++) {
await request(app)
.post('/api/auth/login')
.send({ email: 'test@example.com', password: 'wrong' })
}
// 6th attempt should be rate limited
const response = await request(app)
.post('/api/auth/login')
.send({ email: 'test@example.com', password: 'correct' })
expect(response.status).toBe(429)
})
it('should not leak user existence', async () => {
const response1 = await request(app)
.post('/api/auth/login')
.send({ email: 'exists@example.com', password: 'wrong' })
const response2 = await request(app)
.post('/api/auth/login')
.send({ email: 'notexists@example.com', password: 'wrong' })
expect(response1.body.error).toBe(response2.body.error)
})
})
describe('Input Validation', () => {
it('should prevent SQL injection', async () => {
const maliciousInput = "'; DROP TABLE users; --"
const response = await request(app)
.get(`/api/users/search?q=${maliciousInput}`)
expect(response.status).toBe(400)
// Verify table still exists
const users = await db.users.count()
expect(users).toBeGreaterThan(0)
})
})
})2. Security Checklist
Run through this checklist before deployment:
- [ ] All inputs validated and sanitized
- [ ] Authentication implemented correctly
- [ ] Authorization checks on all endpoints
- [ ] Sensitive data encrypted
- [ ] HTTPS enforced
- [ ] Security headers configured
- [ ] Rate limiting in place
- [ ] Error messages don't leak information
- [ ] Audit logging implemented
- [ ] Dependencies updated and audited
- [ ] Security tests passing
- [ ] Penetration testing completed
Compliance
GDPR Compliance
bash
# Add GDPR features
/add-enterprise-feature "GDPR compliance"HIPAA Compliance
bash
# Healthcare data security
/security-audit --compliance HIPAAPCI DSS Compliance
bash
# Payment card security
/security-audit --compliance PCI-DSSSecurity Resources
Next Steps
- Review Team Collaboration
- Run
/security-auditon your project - Implement missing security measures
- Schedule regular security reviews
