[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M730TXPRXHTT2XS4VMFJKCDK":3,"skill-same:01M730TXPRXHTT2XS4VMFJKCDK":54},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":6,"ownerHtmlUrl":30,"ownerBlogUrl":31,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M730TXPRXHTT2XS4VMFJKCDK","security-review",null,"Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment\u002Fsensitive features. Provides comprehensive security checklist and patterns.","SriramGandhiS\u002FSkills","SriramGandhiS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F211849986?v=4","01M72WQCW12BYX71C6WN584TTA","Sriram S","01M72WQCWTJ2RD0ET1X31AF1RC",1,"MIT","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fskills\u002Feverything-claude-code\u002Fskills\u002Fsecurity-review\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: security-review\ndescription: Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment\u002Fsensitive features. Provides comprehensive security checklist and patterns.\norigin: ECC\n---\n\n# Security Review Skill\n\nThis skill ensures all code follows security best practices and identifies potential vulnerabilities.\n\n## When to Activate\n\n- Implementing authentication or authorization\n- Handling user input or file uploads\n- Creating new API endpoints\n- Working with secrets or credentials\n- Implementing payment features\n- Storing or transmitting sensitive data\n- Integrating third-party APIs\n\n## Security Checklist\n\n### 1. Secrets Management\n\n#### FAIL: NEVER Do This\n```typescript\nconst apiKey = \"sk-proj-xxxxx\"  \u002F\u002F Hardcoded secret\nconst dbPassword = \"password123\" \u002F\u002F In source code\n```\n\n#### PASS: ALWAYS Do This\n```typescript\nconst apiKey = process.env.OPENAI_API_KEY\nconst dbUrl = process.env.DATABASE_URL\n\n\u002F\u002F Verify secrets exist\nif (!apiKey) {\n  throw new Error('OPENAI_API_KEY not configured')\n}\n```\n\n#### Verification Steps\n- [ ] No hardcoded API keys, tokens, or passwords\n- [ ] All secrets in environment variables\n- [ ] `.env.local` in .gitignore\n- [ ] No secrets in git history\n- [ ] Production secrets in hosting platform (Vercel, Railway)\n\n### 2. Input Validation\n\n#### Always Validate User Input\n```typescript\nimport { z } from 'zod'\n\n\u002F\u002F Define validation schema\nconst CreateUserSchema = z.object({\n  email: z.string().email(),\n  name: z.string().min(1).max(100),\n  age: z.number().int().min(0).max(150)\n})\n\n\u002F\u002F Validate before processing\nexport async function createUser(input: unknown) {\n  try {\n    const validated = CreateUserSchema.parse(input)\n    return await db.users.create(validated)\n  } catch (error) {\n    if (error instanceof z.ZodError) {\n      return { success: false, errors: error.errors }\n    }\n    throw error\n  }\n}\n```\n\n#### File Upload Validation\n```typescript\nfunction validateFileUpload(file: File) {\n  \u002F\u002F Size check (5MB max)\n  const maxSize = 5 * 1024 * 1024\n  if (file.size > maxSize) {\n    throw new Error('File too large (max 5MB)')\n  }\n\n  \u002F\u002F Type check\n  const allowedTypes = ['image\u002Fjpeg', 'image\u002Fpng', 'image\u002Fgif']\n  if (!allowedTypes.includes(file.type)) {\n    throw new Error('Invalid file type')\n  }\n\n  \u002F\u002F Extension check\n  const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif']\n  const extension = file.name.toLowerCase().match(\u002F\\.[^.]+$\u002F)?.[0]\n  if (!extension || !allowedExtensions.includes(extension)) {\n    throw new Error('Invalid file extension')\n  }\n\n  return true\n}\n```\n\n#### Verification Steps\n- [ ] All user inputs validated with schemas\n- [ ] File uploads restricted (size, type, extension)\n- [ ] No direct use of user input in queries\n- [ ] Whitelist validation (not blacklist)\n- [ ] Error messages don't leak sensitive info\n\n### 3. SQL Injection Prevention\n\n#### FAIL: NEVER Concatenate SQL\n```typescript\n\u002F\u002F DANGEROUS - SQL Injection vulnerability\nconst query = `SELECT * FROM users WHERE email = '${userEmail}'`\nawait db.query(query)\n```\n\n#### PASS: ALWAYS Use Parameterized Queries\n```typescript\n\u002F\u002F Safe - parameterized query\nconst { data } = await supabase\n  .from('users')\n  .select('*')\n  .eq('email', userEmail)\n\n\u002F\u002F Or with raw SQL\nawait db.query(\n  'SELECT * FROM users WHERE email = $1',\n  [userEmail]\n)\n```\n\n#### Verification Steps\n- [ ] All database queries use parameterized queries\n- [ ] No string concatenation in SQL\n- [ ] ORM\u002Fquery builder used correctly\n- [ ] Supabase queries properly sanitized\n\n### 4. Authentication & Authorization\n\n#### JWT Token Handling\n```typescript\n\u002F\u002F FAIL: WRONG: localStorage (vulnerable to XSS)\nlocalStorage.setItem('token', token)\n\n\u002F\u002F PASS: CORRECT: httpOnly cookies\nres.setHeader('Set-Cookie',\n  `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)\n```\n\n#### Authorization Checks\n```typescript\nexport async function deleteUser(userId: string, requesterId: string) {\n  \u002F\u002F ALWAYS verify authorization first\n  const requester = await db.users.findUnique({\n    where: { id: requesterId }\n  })\n\n  if (requester.role !== 'admin') {\n    return NextResponse.json(\n      { error: 'Unauthorized' },\n      { status: 403 }\n    )\n  }\n\n  \u002F\u002F Proceed with deletion\n  await db.users.delete({ where: { id: userId } })\n}\n```\n\n#### Row Level Security (Supabase)\n```sql\n-- Enable RLS on all tables\nALTER TABLE users ENABLE ROW LEVEL SECURITY;\n\n-- Users can only view their own data\nCREATE POLICY \"Users view own data\"\n  ON users FOR SELECT\n  USING (auth.uid() = id);\n\n-- Users can only update their own data\nCREATE POLICY \"Users update own data\"\n  ON users FOR UPDATE\n  USING (auth.uid() = id);\n```\n\n#### Verification Steps\n- [ ] Tokens stored in httpOnly cookies (not localStorage)\n- [ ] Authorization checks before sensitive operations\n- [ ] Row Level Security enabled in Supabase\n- [ ] Role-based access control implemented\n- [ ] Session management secure\n\n### 5. XSS Prevention\n\n#### Sanitize HTML\n```typescript\nimport DOMPurify from 'isomorphic-dompurify'\n\n\u002F\u002F ALWAYS sanitize user-provided HTML\nfunction renderUserContent(html: string) {\n  const clean = DOMPurify.sanitize(html, {\n    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],\n    ALLOWED_ATTR: []\n  })\n  return \u003Cdiv dangerouslySetInnerHTML={{ __html: clean }} \u002F>\n}\n```\n\n#### Content Security Policy\n\nStart strict and loosen only with a documented removal plan. Do not default to\n`'unsafe-inline'` or `'unsafe-eval'`; they neutralize much of CSP's protection\nand should be treated as temporary compatibility debt.\n\n```typescript\n\u002F\u002F next.config.js\nconst securityHeaders = [\n  {\n    key: 'Content-Security-Policy',\n    value: `\n      default-src 'self';\n      base-uri 'self';\n      object-src 'none';\n      frame-ancestors 'none';\n      script-src 'self';\n      style-src 'self';\n      img-src 'self' data: https:;\n      font-src 'self';\n      connect-src 'self' https:\u002F\u002Fapi.example.com;\n    `.replace(\u002F\\s{2,}\u002Fg, ' ').trim()\n  }\n]\n```\n\n#### Verification Steps\n- [ ] User-provided HTML sanitized\n- [ ] CSP headers configured\n- [ ] No unvalidated dynamic content rendering\n- [ ] React's built-in XSS protection used\n\n### 6. CSRF Protection\n\n#### CSRF Tokens\n```typescript\nimport { csrf } from '@\u002Flib\u002Fcsrf'\n\nexport async function POST(request: Request) {\n  const token = request.headers.get('X-CSRF-Token')\n\n  if (!csrf.verify(token)) {\n    return NextResponse.json(\n      { error: 'Invalid CSRF token' },\n      { status: 403 }\n    )\n  }\n\n  \u002F\u002F Process request\n}\n```\n\n#### SameSite Cookies\n```typescript\nres.setHeader('Set-Cookie',\n  `session=${sessionId}; HttpOnly; Secure; SameSite=Strict`)\n```\n\n#### Verification Steps\n- [ ] CSRF tokens on state-changing operations\n- [ ] SameSite=Strict on all cookies\n- [ ] Double-submit cookie pattern implemented\n\n### 7. Rate Limiting\n\n#### API Rate Limiting\n```typescript\nimport rateLimit from 'express-rate-limit'\n\nconst limiter = rateLimit({\n  windowMs: 15 * 60 * 1000, \u002F\u002F 15 minutes\n  max: 100, \u002F\u002F 100 requests per window\n  message: 'Too many requests'\n})\n\n\u002F\u002F Apply to routes\napp.use('\u002Fapi\u002F', limiter)\n```\n\n#### Expensive Operations\n```typescript\n\u002F\u002F Aggressive rate limiting for searches\nconst searchLimiter = rateLimit({\n  windowMs: 60 * 1000, \u002F\u002F 1 minute\n  max: 10, \u002F\u002F 10 requests per minute\n  message: 'Too many search requests'\n})\n\napp.use('\u002Fapi\u002Fsearch', searchLimiter)\n```\n\n#### Verification Steps\n- [ ] Rate limiting on all API endpoints\n- [ ] Stricter limits on expensive operations\n- [ ] IP-based rate limiting\n- [ ] User-based rate limiting (authenticated)\n\n### 8. Sensitive Data Exposure\n\n#### Logging\n```typescript\n\u002F\u002F FAIL: WRONG: Logging sensitive data\nconsole.log('User login:', { email, password })\nconsole.log('Payment:', { cardNumber, cvv })\n\n\u002F\u002F PASS: CORRECT: Redact sensitive data\nconsole.log('User login:', { email, userId })\nconsole.log('Payment:', { last4: card.last4, userId })\n```\n\n#### Error Messages\n```typescript\n\u002F\u002F FAIL: WRONG: Exposing internal details\ncatch (error) {\n  return NextResponse.json(\n    { error: error.message, stack: error.stack },\n    { status: 500 }\n  )\n}\n\n\u002F\u002F PASS: CORRECT: Generic error messages\ncatch (error) {\n  console.error('Internal error:', error)\n  return NextResponse.json(\n    { error: 'An error occurred. Please try again.' },\n    { status: 500 }\n  )\n}\n```\n\n#### Verification Steps\n- [ ] No passwords, tokens, or secrets in logs\n- [ ] Error messages generic for users\n- [ ] Detailed errors only in server logs\n- [ ] No stack traces exposed to users\n\n### 9. Blockchain Security (Solana)\n\n#### Wallet Verification\n```typescript\nimport { verify } from '@solana\u002Fweb3.js'\n\nasync function verifyWalletOwnership(\n  publicKey: string,\n  signature: string,\n  message: string\n) {\n  try {\n    const isValid = verify(\n      Buffer.from(message),\n      Buffer.from(signature, 'base64'),\n      Buffer.from(publicKey, 'base64')\n    )\n    return isValid\n  } catch (error) {\n    return false\n  }\n}\n```\n\n#### Transaction Verification\n```typescript\nasync function verifyTransaction(transaction: Transaction) {\n  \u002F\u002F Verify recipient\n  if (transaction.to !== expectedRecipient) {\n    throw new Error('Invalid recipient')\n  }\n\n  \u002F\u002F Verify amount\n  if (transaction.amount > maxAmount) {\n    throw new Error('Amount exceeds limit')\n  }\n\n  \u002F\u002F Verify user has sufficient balance\n  const balance = await getBalance(transaction.from)\n  if (balance \u003C transaction.amount) {\n    throw new Error('Insufficient balance')\n  }\n\n  return true\n}\n```\n\n#### Verification Steps\n- [ ] Wallet signatures verified\n- [ ] Transaction details validated\n- [ ] Balance checks before transactions\n- [ ] No blind transaction signing\n\n### 10. Dependency Security\n\n#### Regular Updates\n```bash\n# Check for vulnerabilities\nnpm audit\n\n# Fix automatically fixable issues\nnpm audit fix\n\n# Update dependencies\nnpm update\n\n# Check for outdated packages\nnpm outdated\n```\n\n#### Lock Files\n```bash\n# ALWAYS commit lock files\ngit add package-lock.json\n\n# Use in CI\u002FCD for reproducible builds\nnpm ci  # Instead of npm install\n```\n\n#### Verification Steps\n- [ ] Dependencies up to date\n- [ ] No known vulnerabilities (npm audit clean)\n- [ ] Lock files committed\n- [ ] Dependabot enabled on GitHub\n- [ ] Regular security updates\n\n## Security Testing\n\n### Automated Security Tests\n```typescript\n\u002F\u002F Test authentication\ntest('requires authentication', async () => {\n  const response = await fetch('\u002Fapi\u002Fprotected')\n  expect(response.status).toBe(401)\n})\n\n\u002F\u002F Test authorization\ntest('requires admin role', async () => {\n  const response = await fetch('\u002Fapi\u002Fadmin', {\n    headers: { Authorization: `Bearer ${userToken}` }\n  })\n  expect(response.status).toBe(403)\n})\n\n\u002F\u002F Test input validation\ntest('rejects invalid input', async () => {\n  const response = await fetch('\u002Fapi\u002Fusers', {\n    method: 'POST',\n    body: JSON.stringify({ email: 'not-an-email' })\n  })\n  expect(response.status).toBe(400)\n})\n\n\u002F\u002F Test rate limiting\ntest('enforces rate limits', async () => {\n  const requests = Array(101).fill(null).map(() =>\n    fetch('\u002Fapi\u002Fendpoint')\n  )\n\n  const responses = await Promise.all(requests)\n  const tooManyRequests = responses.filter(r => r.status === 429)\n\n  expect(tooManyRequests.length).toBeGreaterThan(0)\n})\n```\n\n## Pre-Deployment Security Checklist\n\nBefore ANY production deployment:\n\n- [ ] **Secrets**: No hardcoded secrets, all in env vars\n- [ ] **Input Validation**: All user inputs validated\n- [ ] **SQL Injection**: All queries parameterized\n- [ ] **XSS**: User content sanitized\n- [ ] **CSRF**: Protection enabled\n- [ ] **Authentication**: Proper token handling\n- [ ] **Authorization**: Role checks in place\n- [ ] **Rate Limiting**: Enabled on all endpoints\n- [ ] **HTTPS**: Enforced in production\n- [ ] **Security Headers**: CSP, X-Frame-Options configured\n- [ ] **Error Handling**: No sensitive data in errors\n- [ ] **Logging**: No sensitive data logged\n- [ ] **Dependencies**: Up to date, no vulnerabilities\n- [ ] **Row Level Security**: Enabled in Supabase\n- [ ] **CORS**: Properly configured\n- [ ] **File Uploads**: Validated (size, type)\n- [ ] **Wallet Signatures**: Verified (if blockchain)\n\n## Resources\n\n- [OWASP Top 10](https:\u002F\u002Fowasp.org\u002Fwww-project-top-ten\u002F)\n- [Next.js Security](https:\u002F\u002Fnextjs.org\u002Fdocs\u002Fsecurity)\n- [Supabase Security](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth)\n- [Web Security Academy](https:\u002F\u002Fportswigger.net\u002Fweb-security)\n\n---\n\n**Remember**: Security is not optional. One vulnerability can compromise the entire platform. When in doubt, err on the side of caution.\n","# Security Review Skill\n\nThis skill ensures all code follows security best practices and identifies potential vulnerabilities.\n\n## When to Activate\n\n- Implementing authentication or authorization\n- Handling user input or file uploads\n- Creating new API endpoints\n- Working with secrets or credentials\n- Implementing payment features\n- Storing or transmitting sensitive data\n- Integrating third-party APIs\n\n## Security Checklist\n\n### 1. Secrets Management\n\n#### FAIL: NEVER Do This\n```typescript\nconst apiKey = \"sk-proj-xxxxx\"  \u002F\u002F Hardcoded secret\nconst dbPassword = \"password123\" \u002F\u002F In source code\n```\n\n#### PASS: ALWAYS Do This\n```typescript\nconst apiKey = process.env.OPENAI_API_KEY\nconst dbUrl = process.env.DATABASE_URL\n\n\u002F\u002F Verify secrets exist\nif (!apiKey) {\n  throw new Error('OPENAI_API_KEY not configured')\n}\n```\n\n#### Verification Steps\n- [ ] No hardcoded API keys, tokens, or passwords\n- [ ] All secrets in environment variables\n- [ ] `.env.local` in .gitignore\n- [ ] No secrets in git history\n- [ ] Production secrets in hosting platform (Vercel, Railway)\n\n### 2. Input Validation\n\n#### Always Validate User Input\n```typescript\nimport { z } from 'zod'\n\n\u002F\u002F Define validation schema\nconst CreateUserSchema = z.object({\n  email: z.string().email(),\n  name: z.string().min(1).max(100),\n  age: z.number().int().min(0).max(150)\n})\n\n\u002F\u002F Validate before processing\nexport async function createUser(input: unknown) {\n  try {\n    const validated = CreateUserSchema.parse(input)\n    return await db.users.create(validated)\n  } catch (error) {\n    if (error instanceof z.ZodError) {\n      return { success: false, errors: error.errors }\n    }\n    throw error\n  }\n}\n```\n\n#### File Upload Validation\n```typescript\nfunction validateFileUpload(file: File) {\n  \u002F\u002F Size check (5MB max)\n  const maxSize = 5 * 1024 * 1024\n  if (file.size > maxSize) {\n    throw new Error('File too large (max 5MB)')\n  }\n\n  \u002F\u002F Type check\n  const allowedTypes = ['image\u002Fjpeg', 'image\u002Fpng', 'image\u002Fgif']\n  if (!allowedTypes.includes(file.type)) {\n    throw new Error('Invalid file type')\n  }\n\n  \u002F\u002F Extension check\n  const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif']\n  const extension = file.name.toLowerCase().match(\u002F\\.[^.]+$\u002F)?.[0]\n  if (!extension || !allowedExtensions.includes(extension)) {\n    throw new Error('Invalid file extension')\n  }\n\n  return true\n}\n```\n\n#### Verification Steps\n- [ ] All user inputs validated with schemas\n- [ ] File uploads restricted (size, type, extension)\n- [ ] No direct use of user input in queries\n- [ ] Whitelist validation (not blacklist)\n- [ ] Error messages don't leak sensitive info\n\n### 3. SQL Injection Prevention\n\n#### FAIL: NEVER Concatenate SQL\n```typescript\n\u002F\u002F DANGEROUS - SQL Injection vulnerability\nconst query = `SELECT * FROM users WHERE email = '${userEmail}'`\nawait db.query(query)\n```\n\n#### PASS: ALWAYS Use Parameterized Queries\n```typescript\n\u002F\u002F Safe - parameterized query\nconst { data } = await supabase\n  .from('users')\n  .select('*')\n  .eq('email', userEmail)\n\n\u002F\u002F Or with raw SQL\nawait db.query(\n  'SELECT * FROM users WHERE email = $1',\n  [userEmail]\n)\n```\n\n#### Verification Steps\n- [ ] All database queries use parameterized queries\n- [ ] No string concatenation in SQL\n- [ ] ORM\u002Fquery builder used correctly\n- [ ] Supabase queries properly sanitized\n\n### 4. Authentication & Authorization\n\n#### JWT Token Handling\n```typescript\n\u002F\u002F FAIL: WRONG: localStorage (vulnerable to XSS)\nlocalStorage.setItem('token', token)\n\n\u002F\u002F PASS: CORRECT: httpOnly cookies\nres.setHeader('Set-Cookie',\n  `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)\n```\n\n#### Authorization Checks\n```typescript\nexport async function deleteUser(userId: string, requesterId: string) {\n  \u002F\u002F ALWAYS verify authorization first\n  const requester = await db.users.findUnique({\n    where: { id: requesterId }\n  })\n\n  if (requester.role !== 'admin') {\n    return NextResponse.json(\n      { error: 'Unauthorized' },\n      { status: 403 }\n    )\n  }\n\n  \u002F\u002F Proceed with deletion\n  await db.users.delete({ where: { id: userId } })\n}\n```\n\n#### Row Level Security (Supabase)\n```sql\n-- Enable RLS on all tables\nALTER TABLE users ENABLE ROW LEVEL SECURITY;\n\n-- Users can only view their own data\nCREATE POLICY \"Users view own data\"\n  ON users FOR SELECT\n  USING (auth.uid() = id);\n\n-- Users can only update their own data\nCREATE POLICY \"Users update own data\"\n  ON users FOR UPDATE\n  USING (auth.uid() = id);\n```\n\n#### Verification Steps\n- [ ] Tokens stored in httpOnly cookies (not localStorage)\n- [ ] Authorization checks before sensitive operations\n- [ ] Row Level Security enabled in Supabase\n- [ ] Role-based access control implemented\n- [ ] Session management secure\n\n### 5. XSS Prevention\n\n#### Sanitize HTML\n```typescript\nimport DOMPurify from 'isomorphic-dompurify'\n\n\u002F\u002F ALWAYS sanitize user-provided HTML\nfunction renderUserContent(html: string) {\n  const clean = DOMPurify.sanitize(html, {\n    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],\n    ALLOWED_ATTR: []\n  })\n  return \u003Cdiv dangerouslySetInnerHTML={{ __html: clean }} \u002F>\n}\n```\n\n#### Content Security Policy\n\nStart strict and loosen only with a documented removal plan. Do not default to\n`'unsafe-inline'` or `'unsafe-eval'`; they neutralize much of CSP's protection\nand should be treated as temporary compatibility debt.\n\n```typescript\n\u002F\u002F next.config.js\nconst securityHeaders = [\n  {\n    key: 'Content-Security-Policy',\n    value: `\n      default-src 'self';\n      base-uri 'self';\n      object-src 'none';\n      frame-ancestors 'none';\n      script-src 'self';\n      style-src 'self';\n      img-src 'self' data: https:;\n      font-src 'self';\n      connect-src 'self' https:\u002F\u002Fapi.example.com;\n    `.replace(\u002F\\s{2,}\u002Fg, ' ').trim()\n  }\n]\n```\n\n#### Verification Steps\n- [ ] User-provided HTML sanitized\n- [ ] CSP headers configured\n- [ ] No unvalidated dynamic content rendering\n- [ ] React's built-in XSS protection used\n\n### 6. CSRF Protection\n\n#### CSRF Tokens\n```typescript\nimport { csrf } from '@\u002Flib\u002Fcsrf'\n\nexport async function POST(request: Request) {\n  const token = request.headers.get('X-CSRF-Token')\n\n  if (!csrf.verify(token)) {\n    return NextResponse.json(\n      { error: 'Invalid CSRF token' },\n      { status: 403 }\n    )\n  }\n\n  \u002F\u002F Process request\n}\n```\n\n#### SameSite Cookies\n```typescript\nres.setHeader('Set-Cookie',\n  `session=${sessionId}; HttpOnly; Secure; SameSite=Strict`)\n```\n\n#### Verification Steps\n- [ ] CSRF tokens on state-changing operations\n- [ ] SameSite=Strict on all cookies\n- [ ] Double-submit cookie pattern implemented\n\n### 7. Rate Limiting\n\n#### API Rate Limiting\n```typescript\nimport rateLimit from 'express-rate-limit'\n\nconst limiter = rateLimit({\n  windowMs: 15 * 60 * 1000, \u002F\u002F 15 minutes\n  max: 100, \u002F\u002F 100 requests per window\n  message: 'Too many requests'\n})\n\n\u002F\u002F Apply to routes\napp.use('\u002Fapi\u002F', limiter)\n```\n\n#### Expensive Operations\n```typescript\n\u002F\u002F Aggressive rate limiting for searches\nconst searchLimiter = rateLimit({\n  windowMs: 60 * 1000, \u002F\u002F 1 minute\n  max: 10, \u002F\u002F 10 requests per minute\n  message: 'Too many search requests'\n})\n\napp.use('\u002Fapi\u002Fsearch', searchLimiter)\n```\n\n#### Verification Steps\n- [ ] Rate limiting on all API endpoints\n- [ ] Stricter limits on expensive operations\n- [ ] IP-based rate limiting\n- [ ] User-based rate limiting (authenticated)\n\n### 8. Sensitive Data Exposure\n\n#### Logging\n```typescript\n\u002F\u002F FAIL: WRONG: Logging sensitive data\nconsole.log('User login:', { email, password })\nconsole.log('Payment:', { cardNumber, cvv })\n\n\u002F\u002F PASS: CORRECT: Redact sensitive data\nconsole.log('User login:', { email, userId })\nconsole.log('Payment:', { last4: card.last4, userId })\n```\n\n#### Error Messages\n```typescript\n\u002F\u002F FAIL: WRONG: Exposing internal details\ncatch (error) {\n  return NextResponse.json(\n    { error: error.message, stack: error.stack },\n    { status: 500 }\n  )\n}\n\n\u002F\u002F PASS: CORRECT: Generic error messages\ncatch (error) {\n  console.error('Internal error:', error)\n  return NextResponse.json(\n    { error: 'An error occurred. Please try again.' },\n    { status: 500 }\n  )\n}\n```\n\n#### Verification Steps\n- [ ] No passwords, tokens, or secrets in logs\n- [ ] Error messages generic for users\n- [ ] Detailed errors only in server logs\n- [ ] No stack traces exposed to users\n\n### 9. Blockchain Security (Solana)\n\n#### Wallet Verification\n```typescript\nimport { verify } from '@solana\u002Fweb3.js'\n\nasync function verifyWalletOwnership(\n  publicKey: string,\n  signature: string,\n  message: string\n) {\n  try {\n    const isValid = verify(\n      Buffer.from(message),\n      Buffer.from(signature, 'base64'),\n      Buffer.from(publicKey, 'base64')\n    )\n    return isValid\n  } catch (error) {\n    return false\n  }\n}\n```\n\n#### Transaction Verification\n```typescript\nasync function verifyTransaction(transaction: Transaction) {\n  \u002F\u002F Verify recipient\n  if (transaction.to !== expectedRecipient) {\n    throw new Error('Invalid recipient')\n  }\n\n  \u002F\u002F Verify amount\n  if (transaction.amount > maxAmount) {\n    throw new Error('Amount exceeds limit')\n  }\n\n  \u002F\u002F Verify user has sufficient balance\n  const balance = await getBalance(transaction.from)\n  if (balance \u003C transaction.amount) {\n    throw new Error('Insufficient balance')\n  }\n\n  return true\n}\n```\n\n#### Verification Steps\n- [ ] Wallet signatures verified\n- [ ] Transaction details validated\n- [ ] Balance checks before transactions\n- [ ] No blind transaction signing\n\n### 10. Dependency Security\n\n#### Regular Updates\n```bash\n# Check for vulnerabilities\nnpm audit\n\n# Fix automatically fixable issues\nnpm audit fix\n\n# Update dependencies\nnpm update\n\n# Check for outdated packages\nnpm outdated\n```\n\n#### Lock Files\n```bash\n# ALWAYS commit lock files\ngit add package-lock.json\n\n# Use in CI\u002FCD for reproducible builds\nnpm ci  # Instead of npm install\n```\n\n#### Verification Steps\n- [ ] Dependencies up to date\n- [ ] No known vulnerabilities (npm audit clean)\n- [ ] Lock files committed\n- [ ] Dependabot enabled on GitHub\n- [ ] Regular security updates\n\n## Security Testing\n\n### Automated Security Tests\n```typescript\n\u002F\u002F Test authentication\ntest('requires authentication', async () => {\n  const response = await fetch('\u002Fapi\u002Fprotected')\n  expect(response.status).toBe(401)\n})\n\n\u002F\u002F Test authorization\ntest('requires admin role', async () => {\n  const response = await fetch('\u002Fapi\u002Fadmin', {\n    headers: { Authorization: `Bearer ${userToken}` }\n  })\n  expect(response.status).toBe(403)\n})\n\n\u002F\u002F Test input validation\ntest('rejects invalid input', async () => {\n  const response = await fetch('\u002Fapi\u002Fusers', {\n    method: 'POST',\n    body: JSON.stringify({ email: 'not-an-email' })\n  })\n  expect(response.status).toBe(400)\n})\n\n\u002F\u002F Test rate limiting\ntest('enforces rate limits', async () => {\n  const requests = Array(101).fill(null).map(() =>\n    fetch('\u002Fapi\u002Fendpoint')\n  )\n\n  const responses = await Promise.all(requests)\n  const tooManyRequests = responses.filter(r => r.status === 429)\n\n  expect(tooManyRequests.length).toBeGreaterThan(0)\n})\n```\n\n## Pre-Deployment Security Checklist\n\nBefore ANY production deployment:\n\n- [ ] **Secrets**: No hardcoded secrets, all in env vars\n- [ ] **Input Validation**: All user inputs validated\n- [ ] **SQL Injection**: All queries parameterized\n- [ ] **XSS**: User content sanitized\n- [ ] **CSRF**: Protection enabled\n- [ ] **Authentication**: Proper token handling\n- [ ] **Authorization**: Role checks in place\n- [ ] **Rate Limiting**: Enabled on all endpoints\n- [ ] **HTTPS**: Enforced in production\n- [ ] **Security Headers**: CSP, X-Frame-Options configured\n- [ ] **Error Handling**: No sensitive data in errors\n- [ ] **Logging**: No sensitive data logged\n- [ ] **Dependencies**: Up to date, no vulnerabilities\n- [ ] **Row Level Security**: Enabled in Supabase\n- [ ] **CORS**: Properly configured\n- [ ] **File Uploads**: Validated (size, type)\n- [ ] **Wallet Signatures**: Verified (if blockchain)\n\n## Resources\n\n- [OWASP Top 10](https:\u002F\u002Fowasp.org\u002Fwww-project-top-ten\u002F)\n- [Next.js Security](https:\u002F\u002Fnextjs.org\u002Fdocs\u002Fsecurity)\n- [Supabase Security](https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth)\n- [Web Security Academy](https:\u002F\u002Fportswigger.net\u002Fweb-security)\n\n---\n\n**Remember**: Security is not optional. One vulnerability can compromise the entire platform. When in doubt, err on the side of caution.\n",{"name":5,"origin":24,"description":7},"ECC","master","d6ca01da0f24a3b0e26e4a8b7b66cbd25d429f5d","skills\u002Feverything-claude-code\u002Fskills\u002Fsecurity-review",0,"https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills","https:\u002F\u002Fgithub.com\u002FSriramGandhiS","https:\u002F\u002Fsriram.website\u002F","Curious guy who keeps tinkering until something works","2026-05-20 16:21:34",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add SriramGandhiS\u002FSkills --skill security-review",{"tool":40,"command":41},"bunx","bunx skills add SriramGandhiS\u002FSkills --skill security-review",{"tool":43,"command":44},"pnpm","pnpm dlx skills add SriramGandhiS\u002FSkills --skill security-review","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fskills\u002Feverything-claude-code\u002Fskills\u002Fsecurity-review\u002FSKILL.md",true,[48],{"path":49,"resourceType":50,"resourceTypeDesc":51,"sizeBytes":52,"sourceHtmlUrl":53},"cloud-infrastructure-security.md","REFERENCE","参考文档",10171,"https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fskills\u002Feverything-claude-code\u002Fskills\u002Fsecurity-review\u002Fcloud-infrastructure-security.md",[55,62,67,73,80,87],{"skillNo":56,"name":57,"nameZh":6,"description":58,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":61,"publishedAt":19},"01M732609EPJWV13PVTX3GT4TM","webgpu-threejs-tsl","Comprehensive guide for developing WebGPU-enabled Three.js applications using TSL (Three.js Shading Language). Covers WebGPU renderer setup, TSL syntax and node materials, compute shaders, post-processing effects, and WGSL integration. Use this skill when working with Three.js WebGPU, TSL shaders, node materials, or GPU compute in Three.js.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002Fskills\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],{"skillNo":63,"name":57,"nameZh":6,"description":58,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M7325XM47AGWB6K6C4VXKE6B","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fwebgpu-threejs-tsl\u002FSKILL.md",[],[],{"skillNo":68,"name":69,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":72,"publishedAt":19},"01M7325WP6DES69JKC840VMFEP","verification-loop","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":19},"01M7325TFQF1DZTQ6J3WGQQ1VR","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[],[],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":19},"01M7325RGV9AY9PK92D2V8KKPW","strategic-compact","Suggests manual context compaction at logical intervals to preserve context through task phases rather than arbitrary auto-compaction.","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fstrategic-compact\u002FSKILL.md",[],[],{"skillNo":88,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":91,"publishedAt":19},"01M7325MZC28SE86E7NMCNEFS4","https:\u002F\u002Fgithub.com\u002FSriramGandhiS\u002FSkills\u002Fblob\u002Fmaster\u002Fweb-assets\u002Fdocs\u002Fzh-TW\u002Fskills\u002Fsecurity-review\u002FSKILL.md",[],[]]