Smithery Logo
MCPsSkillsDocsPricing
Login
NewFlame, an assistant that learns and improves. Available onTelegramSlack
    daffy0208

    security-engineer

    daffy0208/security-engineer
    Productivity
    9

    About

    SKILL.md

    Install

    • Telegram
      Telegram
    • Slack
      Slack
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    • Download skill
    ├─
    ├─
    └─
    Smithery Logo

    Give agents more agency

    Resources

    DocumentationPrivacy PolicySystem Status

    Company

    PricingAboutBlog

    Connect

    © 2026 Smithery. All rights reserved.

    About

    Implement security best practices across the application stack. Use when securing APIs, implementing authentication, preventing vulnerabilities, or conducting security reviews...

    SKILL.md

    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:

    • OWASP Top 10
    • OWASP Cheat Sheet Series
    • Security Headers

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

    Recommended Servers
    Infisical
    Infisical
    OpenZeppelin
    OpenZeppelin
    Agent Safe Message MCP
    Agent Safe Message MCP
    Repository
    daffy0208/ai-dev-standards
    Files