Skip to content

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-fixes

2. 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, sanitization

Authentication & 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 HIPAA

PCI DSS Compliance

bash
# Payment card security
/security-audit --compliance PCI-DSS

Security Resources

Next Steps

  • Review Team Collaboration
  • Run /security-audit on your project
  • Implement missing security measures
  • Schedule regular security reviews

Built with ❤️ for the AI Coding community, by Praney Behl