security engineer

📁 daffy0208/ai-dev-standards 📅 Jan 1, 1970
50
总安装量
0
周安装量
#4249
全站排名
安装命令
npx skills add https://github.com/daffy0208/ai-dev-standards --skill Security Engineer

Skill 文档

Security Engineer

Security is not optional – build it in from day one.

Core Principle

Security is built-in, not bolted-on.

Every feature, every endpoint, every data flow must consider security implications. Security vulnerabilities cost 10x more to fix in production than during development.

5 Security Pillars

Pillar 1: Authentication & Authorization 🔐

Authentication: Who are you? Authorization: What can you do?

Authentication Strategies

JWT (JSON Web Tokens):

  • When: Stateless APIs, mobile apps, microservices
  • How: Sign tokens with secret, store in httpOnly cookies or Authorization header
  • Security: Use RS256 (not HS256), short expiry (15min access, 7d refresh)
// Example: Next.js API with JWT
import { SignJWT, jwtVerify } from 'jose'

const secret = new TextEncoder().encode(process.env.JWT_SECRET!)

export async function createToken(userId: string) {
  return await new SignJWT({ userId })
    .setProtectedHeader({ alg: 'HS256' })
    .setExpirationTime('15m')
    .sign(secret)
}

export async function verifyToken(token: string) {
  const { payload } = await jwtVerify(token, secret)
  return payload
}

Session-Based:

  • When: Traditional web apps, server-side rendering
  • How: Server stores session ID in encrypted cookie
  • Security: HttpOnly, Secure, SameSite=Strict cookies

OAuth 2.0 / OIDC:

  • When: Social login, third-party integrations
  • How: Use NextAuth.js, Passport.js, or Auth0
  • Security: Validate state parameter, use PKCE for mobile

Authorization Patterns

RBAC (Role-Based Access Control):

// Define roles
enum Role {
  ADMIN = 'admin',
  USER = 'user',
  GUEST = 'guest'
}

// Check permissions
function requireRole(allowedRoles: Role[]) {
  return (req, res, next) => {
    if (!allowedRoles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Forbidden' })
    }
    next()
  }
}

// Usage
app.delete('/api/users/:id', requireRole([Role.ADMIN]), deleteUser)

ABAC (Attribute-Based):

  • More granular: user can edit resource if they created it
  • Example: User can delete post only if post.authorId === user.id

Key Principles:

  • ✅ Always verify authentication before authorization
  • ✅ Default deny (whitelist, not blacklist)
  • ✅ Check permissions on server, never trust client
  • ✅ Re-verify permissions before critical actions

Pillar 2: Input Validation & Sanitization 🛡️

Never trust user input – validate, sanitize, escape everything.

Prevent SQL Injection

❌ Bad (Vulnerable):

// DON'T DO THIS!
const query = `SELECT * FROM users WHERE email = '${userInput}'`
db.query(query) // SQL injection vulnerability!

✅ Good (Parameterized Queries):

// Always use parameterized queries
const query = 'SELECT * FROM users WHERE email = ?'
db.query(query, [userInput]) // Safe - parameterized

// With Prisma
const user = await prisma.user.findUnique({
  where: { email: userInput } // Safe - ORM handles it
})

Prevent XSS (Cross-Site Scripting)

❌ Bad (Vulnerable):

// DON'T DO THIS!
<div dangerouslySetInnerHTML={{ __html: userInput }} />

✅ Good (Escaped):

// React automatically escapes
;<div>{userInput}</div> // Safe

// If you must render HTML, sanitize first
import DOMPurify from 'isomorphic-dompurify'
;<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

Input Validation with Zod

import { z } from 'zod'

const UserSchema = z.object({
  email: z.string().email().max(255),
  password: z.string().min(8).max(100),
  age: z.number().int().min(13).max(120),
  website: z.string().url().optional()
})

// Validate
const result = UserSchema.safeParse(req.body)
if (!result.success) {
  return res.status(400).json({ errors: result.error.issues })
}

const validData = result.data // Type-safe!

File Upload Security

import multer from 'multer'

const upload = multer({
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB max
  },
  fileFilter: (req, file, cb) => {
    // Whitelist file types
    const allowedTypes = ['image/jpeg', 'image/png', 'image/webp']
    if (!allowedTypes.includes(file.mimetype)) {
      return cb(new Error('Invalid file type'))
    }
    cb(null, true)
  }
})

// Generate random filenames (don't trust user input)
const filename = crypto.randomUUID() + path.extname(file.originalname)

Key Principles:

  • ✅ Validate on server (never trust client validation)
  • ✅ Use schema validation libraries (Zod, Yup, Joi)
  • ✅ Whitelist allowed values, don’t blacklist
  • ✅ Escape output based on context (HTML, URL, JS)

Pillar 3: Secure Configuration 🔧

Environment Variables

Never commit secrets:

# .env (add to .gitignore!)
DATABASE_URL="postgresql://user:pass@localhost:5432/db"
JWT_SECRET="generate-with-openssl-rand-base64-32"
OPENAI_API_KEY="sk-..."

Access in code:

// Validate env vars on startup
if (!process.env.JWT_SECRET) {
  throw new Error('JWT_SECRET is required')
}

const config = {
  jwtSecret: process.env.JWT_SECRET,
  databaseUrl: process.env.DATABASE_URL
}

Secret Management (Production):

  • AWS Secrets Manager
  • Vercel Environment Variables
  • HashiCorp Vault
  • Doppler

Security Headers

// Next.js middleware
export function middleware(request: NextRequest) {
  const response = NextResponse.next()

  // Prevent clickjacking
  response.headers.set('X-Frame-Options', 'DENY')

  // Prevent MIME sniffing
  response.headers.set('X-Content-Type-Options', 'nosniff')

  // XSS Protection
  response.headers.set('X-XSS-Protection', '1; mode=block')

  // Content Security Policy
  response.headers.set(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
  )

  // HTTPS only
  response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')

  return response
}

CORS Configuration

// Configure CORS properly
app.use(
  cors({
    origin:
      process.env.NODE_ENV === 'production' ? 'https://yourdomain.com' : 'http://localhost:3000',
    credentials: true, // Allow cookies
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization']
  })
)

Key Principles:

  • ✅ Use environment variables for all secrets
  • ✅ Different secrets per environment (dev, staging, prod)
  • ✅ Rotate secrets regularly
  • ✅ Set security headers on all responses
  • ✅ Configure CORS restrictively

Pillar 4: Data Protection 🔒

Password Hashing

❌ Never store passwords in plain text or use MD5/SHA1!

✅ Use bcrypt or argon2:

import bcrypt from 'bcrypt'

// Hash password (on signup)
const saltRounds = 12
const hashedPassword = await bcrypt.hash(password, saltRounds)
await db.user.create({
  email,
  password: hashedPassword // Store hash, never plain text
})

// Verify password (on login)
const user = await db.user.findUnique({ where: { email } })
const isValid = await bcrypt.compare(password, user.password)
if (!isValid) {
  throw new Error('Invalid credentials')
}

Encryption at Rest

Sensitive data should be encrypted:

import crypto from 'crypto'

const algorithm = 'aes-256-gcm'
const key = Buffer.from(process.env.ENCRYPTION_KEY!, 'hex')

function encrypt(text: string) {
  const iv = crypto.randomBytes(16)
  const cipher = crypto.createCipheriv(algorithm, key, iv)
  const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()])
  const authTag = cipher.getAuthTag()
  return {
    iv: iv.toString('hex'),
    encryptedData: encrypted.toString('hex'),
    authTag: authTag.toString('hex')
  }
}

function decrypt(encrypted: any) {
  const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(encrypted.iv, 'hex'))
  decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'))
  return decipher.update(encrypted.encryptedData, 'hex', 'utf8') + decipher.final('utf8')
}

// Encrypt sensitive fields
const ssn = encrypt(user.ssn)
await db.user.update({ where: { id }, data: { ssnEncrypted: JSON.stringify(ssn) } })

Encryption in Transit

Always use HTTPS:

  • Development: mkcert for local HTTPS
  • Production: Let’s Encrypt, Cloudflare, Vercel (auto HTTPS)

Verify external API certificates:

// Don't disable SSL verification in production!
fetch(url, {
  // DON'T: agent: new https.Agent({ rejectUnauthorized: false })
})

Key Principles:

  • ✅ Hash passwords with bcrypt (12+ rounds) or argon2
  • ✅ Encrypt PII (SSN, credit cards, health data)
  • ✅ Use HTTPS everywhere (enforce with HSTS header)
  • ✅ Encrypt database backups

Pillar 5: Monitoring & Response 📊

Rate Limiting

Prevent brute force and DDoS:

import rateLimit from 'express-rate-limit'

// Global rate limit
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requests per window
  message: 'Too many requests from this IP'
})
app.use(limiter)

// Stricter limit for auth endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5, // Only 5 login attempts per 15min
  skipSuccessfulRequests: true
})
app.post('/api/auth/login', authLimiter, loginHandler)

Audit Logging

Log all security-relevant events:

async function auditLog(event: {
  userId?: string
  action: string
  resource: string
  ip: string
  userAgent: string
  success: boolean
  metadata?: any
}) {
  await db.auditLog.create({
    data: {
      ...event,
      timestamp: new Date()
    }
  })
}

// Usage
await auditLog({
  userId: user.id,
  action: 'LOGIN',
  resource: 'auth',
  ip: req.ip,
  userAgent: req.headers['user-agent'],
  success: true
})

Error Handling

Don’t leak sensitive info in errors:

❌ Bad:

// Exposes database structure!
catch (error) {
  res.status(500).json({ error: error.message })
}

✅ Good:

catch (error) {
  // Log full error server-side
  console.error('Error:', error)

  // Send generic message to client
  res.status(500).json({
    error: 'Internal server error',
    requestId: generateRequestId() // For support
  })
}

Security Monitoring

Tools to integrate:

  • Sentry: Error tracking, security alerts
  • Datadog: APM, anomaly detection
  • CloudWatch: AWS infrastructure monitoring
  • OWASP ZAP: Automated security scans

Key Principles:

  • ✅ Rate limit all public endpoints
  • ✅ Log authentication attempts, authorization failures
  • ✅ Never expose sensitive data in errors
  • ✅ Set up alerts for suspicious patterns
  • ✅ Regular security audits

OWASP Top 10 Quick Reference

# Vulnerability Prevention
1 Broken Access Control Verify permissions server-side, default deny
2 Cryptographic Failures Use TLS, hash passwords (bcrypt), encrypt PII
3 Injection Parameterized queries, input validation
4 Insecure Design Threat modeling, security requirements
5 Security Misconfiguration Secure defaults, remove unused features
6 Vulnerable Components Keep dependencies updated, use Dependabot
7 Auth & Session Issues Strong passwords, MFA, secure session mgmt
8 Software & Data Integrity Verify dependencies, sign releases
9 Logging & Monitoring Failures Log security events, set up alerts
10 SSRF Validate URLs, whitelist allowed domains

Security Checklist (Pre-Deployment)

Authentication

  • Passwords hashed with bcrypt (12+ rounds)
  • JWT tokens use RS256, short expiry
  • Session cookies are HttpOnly, Secure, SameSite
  • Rate limiting on login endpoints (5 attempts/15min)
  • Password reset uses secure tokens (expires 1 hour)

Authorization

  • All routes check authentication
  • Permissions verified server-side
  • Default deny (whitelist approach)
  • No sensitive operations allowed without re-authentication

Input Validation

  • All user input validated with schema (Zod)
  • SQL queries use parameterized queries/ORM
  • File uploads whitelist types and size limits
  • Output escaped based on context

Configuration

  • No secrets in code or version control
  • Environment variables for all config
  • Security headers set (CSP, HSTS, X-Frame-Options)
  • CORS configured restrictively
  • HTTPS enforced in production

Data Protection

  • PII encrypted at rest
  • TLS/HTTPS for all connections
  • Database backups encrypted
  • Secure secret management (Vault, AWS Secrets)

Monitoring

  • Audit logging for security events
  • Error tracking configured (Sentry)
  • Rate limiting on all public endpoints
  • Alerts for failed login attempts, 5xx errors

Dependencies

  • All dependencies up to date
  • Dependabot enabled
  • No known vulnerabilities (run npm audit)
  • Minimal dependencies (remove unused)

Common Security Mistakes

Mistake 1: Client-Side Authorization

❌ Wrong:

// Hiding UI doesn't prevent access!
{
  user.role === 'admin' && <DeleteButton />
}

✅ Right:

// Always verify on server
app.delete('/api/users/:id', requireAdmin, deleteUser)

Mistake 2: Trusting Client Data

❌ Wrong:

// User can manipulate userId in request!
const userId = req.body.userId
await db.order.create({ data: { userId } })

✅ Right:

// Get userId from authenticated session
const userId = req.user.id // From JWT/session
await db.order.create({ data: { userId } })

Mistake 3: Weak Password Requirements

❌ Wrong:

if (password.length < 6) throw new Error('Too short')

✅ Right:

const passwordSchema = z
  .string()
  .min(8, 'At least 8 characters')
  .regex(/[A-Z]/, 'Needs uppercase')
  .regex(/[a-z]/, 'Needs lowercase')
  .regex(/[0-9]/, 'Needs number')

Mistake 4: Insecure Direct Object References

❌ Wrong:

// User can access any document by changing ID!
const doc = await db.document.findUnique({ where: { id: req.params.id } })
return res.json(doc)

✅ Right:

// Verify ownership
const doc = await db.document.findFirst({
  where: {
    id: req.params.id,
    userId: req.user.id // Ensure user owns this document
  }
})
if (!doc) return res.status(404).json({ error: 'Not found' })
return res.json(doc)

Framework-Specific Guidance

Next.js Security

// middleware.ts - Protect routes
export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')

  // Redirect to login if no token
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*', '/api/private/:path*']
}

Express Security

import helmet from 'helmet'
import mongoSanitize from 'express-mongo-sanitize'

app.use(helmet()) // Security headers
app.use(express.json({ limit: '10mb' })) // Prevent large payloads
app.use(mongoSanitize()) // Prevent NoSQL injection

FastAPI Security

from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer

security = HTTPBearer()

async def get_current_user(token: str = Depends(security)):
    try:
        payload = verify_token(token.credentials)
        return payload['user_id']
    except:
        raise HTTPException(status_code=401, detail="Invalid token")

@app.get("/protected")
async def protected_route(user_id: str = Depends(get_current_user)):
    return {"user_id": user_id}

Security Testing

Automated Tools

  • OWASP ZAP: Web vulnerability scanner
  • Snyk: Dependency vulnerability scanning
  • npm audit: Check for known vulnerabilities
  • Lighthouse: Security audit in Chrome DevTools

Manual Testing

  1. Try SQL injection: ' OR '1'='1
  2. Try XSS: <script>alert('XSS')</script>
  3. Try CSRF: Submit form from different origin
  4. Try path traversal: ../../etc/passwd
  5. Try auth bypass: Access admin routes without token

When to Use This Skill

Use security-engineer skill when:

  • ✅ Implementing authentication/authorization
  • ✅ Building API endpoints
  • ✅ Handling sensitive data (PII, payments, health)
  • ✅ Reviewing code for vulnerabilities
  • ✅ Deploying to production
  • ✅ Conducting security audits

Related Resources

Skills:

  • api-designer – API design patterns (pairs with security)
  • testing-strategist – Security testing strategies
  • deployment-advisor – Production security configuration

Patterns:

  • /STANDARDS/architecture-patterns/authentication-patterns.md
  • /STANDARDS/best-practices/security-best-practices.md

External:


Security is everyone’s responsibility. Build it in from day one. 🔒