security-patterns

JasonDocton's avatarfrom JasonDocton

Security patterns for input validation, PII protection, and cryptographic operations

⭐0stars🔀0forks📁View on GitHub🕐Updated Nov 20, 2025

When & Why to Use This Skill

This Claude skill provides a comprehensive framework of security patterns and best practices for modern software development. It focuses on robust input validation using Zod, automated PII (Personally Identifiable Information) protection, secure cryptographic operations, and defensive error handling. By integrating these patterns, developers can effectively mitigate common vulnerabilities such as XSS, SQL injection, and data leaks while ensuring compliance with privacy standards.

Use Cases

  • Implementing strict input validation for API endpoints using Zod schemas to prevent malicious data entry and ensure type safety.
  • Automating PII protection by sanitizing application logs to ensure sensitive user data like emails, tokens, and passwords are never exposed.
  • Securing third-party integrations, such as Stripe webhooks, through cryptographic signature verification and replay attack prevention.
  • Establishing secure authentication workflows using cryptographically secure random number generation and encrypted client-side storage.
  • Designing resilient error handling systems that provide generic feedback to users while logging detailed, sanitized debugging information server-side.
namesecurity-patterns
descriptionSecurity patterns for input validation, PII protection, and cryptographic operations

Security Patterns

Purpose: Security best practices (validation, PII protection, crypto, defense against vulnerabilities)

  • Keywords: security, validation, auth, password, token, sanitize, xss, sql injection, zod, pii, webhook, signature, verify, encrypt, decrypt, hash, jwt, oauth, csrf, authentication, authorization, stripe

Quick Reference

Category ✅ DO ❌ AVOID
Validation Zod schemas with constraints Trust client input
PII sanitizeForLogging() Log emails, names, tokens
Crypto crypto.randomInt() Math.random()
Storage Encrypt localStorage Store keys/passwords
Errors Generic to client Stack traces to client

Input Validation (Zod)

import { z } from "zod"

const orderSchema = z.object({
  name: z.string().min(1).max(100).trim(),
  email: z.string().email().max(255).toLowerCase(),
  amount: z.number().positive().max(1000000),
  phone: z.string().regex(/^\+?[1-9]\d{1,14}$/).optional()
})

type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }

const validate = (input: unknown): Result<Order, z.ZodError> => {
  const result = orderSchema.safeParse(input)
  return result.success
    ? { ok: true, value: result.data }
    : { ok: false, error: result.error }
}

Key: Use .safeParse(), add constraints (.min(), .max(), .trim()), return Result

PII Protection

import { sanitizeForLogging } from "./utils/sanitize"

// ✅ Auto-removes PII
logger.audit('order_created', sanitizeForLogging({
  user_id: "123",
  full_name: "John", // Removed
  email: "john@example.com", // Removed
  amount: 100
}))
// Logged: { user_id: "123", amount: 100 }

Auto-removed: Passwords, tokens, API keys, emails, names, SSN, cards, Bitcoin keys/addresses, phones

See resources/pii-protection.md for implementation.

Secure Random

import { randomInt } from "crypto"

// ✅ Cryptographically secure
const sessionId = randomInt(0, Number.MAX_SAFE_INTEGER).toString(36)
const code = randomInt(100000, 999999).toString()

// ✅ Browser
const array = new Uint32Array(1)
crypto.getRandomValues(array)

// ❌ NEVER for security
const code = Math.random() * 1000000

Secure Client Storage

import { encrypt, decrypt } from "./crypto"

const saveSession = (data: SessionData) => {
  const encrypted = encrypt(JSON.stringify(data))
  localStorage.setItem("session", encrypted)
}

// ❌ NEVER store Bitcoin keys/passwords (even encrypted)

Error Handling

export const createOrder = async (input: unknown) => {
  try {
    const order = await processOrder(input)
    return { ok: true, value: order }
  } catch (error) {
    // ✅ Log full details server-side
    logger.error('Order failed', {
      error,
      stack: error.stack,
      input: sanitizeForLogging(input)
    })

    // ✅ Generic to client
    return {
      ok: false,
      error: new Error("Failed to create order")
    }
  }
}

Webhook Verification

export const handleStripeWebhook = async (req: Request) => {
  const signature = req.headers.get("stripe-signature")
  const body = await req.text()

  // ✅ Verify signature BEFORE processing
  if (!verifySignature(body, signature, WEBHOOK_SECRET)) {
    logger.warn('Invalid signature', { ip: req.headers.get("x-forwarded-for") })
    return new Response("Invalid signature", { status: 401 })
  }

  // ✅ Check timestamp (replay attack)
  const event = JSON.parse(body)
  const eventTime = event.created * 1000
  if (Date.now() - eventTime > 5 * 60 * 1000) {
    return new Response("Timestamp too old", { status: 400 })
  }

  await processWebhookEvent(event)
  return new Response("OK", { status: 200 })
}

Pre-Implementation Checklist

Before implementing, ask:

  1. ✅ Can users access data they shouldn't? (Authorization)
  2. ✅ Can this be automated/abused? (Rate limiting)
  3. ✅ Am I trusting client data? (Validation)
  4. ✅ Could this leak PII? (Sanitization)
  5. ✅ Can concurrent requests cause issues? (Race conditions)
  6. ✅ Can this be spammed? (Rate limiting, CAPTCHA)

If ANY "yes" → redesign before implementing

Rate Limits

Action Limit
Registration 3/IP/24h
Login 10/email/5min
Password reset 3/email/hour
API calls 100/user/hour

See resources/rate-limiting.md

Incident Response

Severity Response Examples
Critical 4 hours Breach, auth bypass
High 24 hours PII leak, privilege escalation
Medium 3 days XSS, CSRF

Steps: Assess → Contain → Investigate → Patch → Notify (<72h if PII)

Resources

  • resources/input-validation.md - Zod patterns
  • resources/pii-protection.md - Sanitization
  • resources/crypto-operations.md - Secure random, encryption
  • resources/rate-limiting.md - Rate limit implementation