Communitygithub.com

보안 검토

인증 추가, 사용자 입력 처리, 비밀 정보 작업, API 엔드포인트 생성 또는 결제/민감 기능 구현 시 이 스킬을 사용하세요. 포괄적인 보안 체크리스트와 패턴을 제공합니다.

보안 검토란 무엇인가요?

이 스킬은 코드가 보안 모범 사례를 따르고 잠재적인 취약점을 식별하도록 보장합니다. 인증, 사용자 입력 처리, API 엔드포인트 생성, 비밀 정보 관리, 결제 기능 구현, 민감 데이터 저장/전송, 타사 API 통합 등 다양한 시나리오에서 활성화하세요. 시크릿 관리, 입력 유효성 검사, SQL 인젝션 방지, 인증 및 권한 부여, XSS 방지, CSRF 보호, 속도 제한, 민감 데이터 노출 방지, 블록체인 보안, 종속성 보안 등 10가지 주요 보안 영역을 다루는 체크리스트를 제공합니다. 각 영역은 '절대 하지 말아야 할 것(FAIL)'과 '항상 이렇게 하라(PASS)'는 구체적인 코드 예제와 함께 단계별 검증 항목을 제시하여 개발자가 실수를 피하고 올바른 보안 패턴을 적용할 수 있도록 돕습니다. Next.js, Supabase, Solana 등 다양한 플랫폼에 특화된 보안 가이드도 포함되어 있습니다.

지원 대상~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/security-review

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

보안 검토 스킬

이 스킬은 모든 코드가 보안 모범 사례를 따르고 잠재적인 취약점을 식별하도록 보장합니다.

활성화 시점

  • 인증 또는 권한 부여 구현
  • 사용자 입력 또는 파일 업로드 처리
  • 새로운 API 엔드포인트 생성
  • 비밀 정보(시크릿) 또는 인증 정보 작업
  • 결제 기능 구현
  • 민감 데이터 저장 또는 전송
  • 타사 API 통합

보안 체크리스트

1. 시크릿(Secrets) 관리

FAIL: 절대 이렇게 하지 마세요

const apiKey = "sk-proj-xxxxx"  // 하드코딩된 시크릿
const dbPassword = "password123" // 소스 코드에 저장

PASS: 항상 이렇게 하세요

const apiKey = process.env.OPENAI_API_KEY
const dbUrl = process.env.DATABASE_URL

// 시크릿이 존재하는지 확인
if (!apiKey) {
  throw new Error('OPENAI_API_KEY가 설정되지 않았습니다.')
}

검증 단계

  • 하드코딩된 API 키, 토큰 또는 비밀번호가 없습니다.
  • 모든 시크릿은 환경 변수에 저장됩니다.
  • .env.local이 .gitignore에 포함되어 있습니다.
  • Git 히스토리에 시크릿이 포함되어 있지 않습니다.
  • 프로덕션 시크릿은 호스팅 플랫폼(Vercel, Railway)에 저장됩니다.

2. 입력 유효성 검사

항상 사용자 입력 검증하기

import { z } from 'zod'

// 검증 스키마 정의
const CreateUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().min(0).max(150)
})

// 처리 전 검증
function createUser(input: unknown) {
  try {
    const validated = CreateUserSchema.parse(input)
    return db.users.create(validated)
  } catch (error) {
    if (error instanceof z.ZodError) {
      return { success: false, errors: error.issues }
    }
    throw error
  }
}

파일 업로드 검증

function validateFileUpload(file: File) {
  // 크기 제한 (최대 5MB)
  const maxSize = 5 * 1024 * 1024
  if (file.size > maxSize) {
    throw new Error('파일이 너무 큽니다 (최대 5MB)')
  }

  // 타입 확인
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
  if (!allowedTypes.includes(file.type)) {
    throw new Error('잘못된 파일 형식입니다.')
  }

  // 확장자 확인
  const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif']
  const extension = file.name.toLowerCase().match(/\.[^.]+$/)?.[0]
  if (!extension || !allowedExtensions.includes(extension)) {
    throw new Error('잘못된 파일 확장자입니다.')
  }

  return true
}

검증 단계

  • 모든 사용자 입력은 스키마로 검증됩니다.
  • 파일 업로드가 제한됩니다 (크기, 타입, 확장자).
  • 쿼리에 사용자 입력이 직접 사용되지 않습니다.
  • 블랙리스트가 아닌 화이트리스트 방식으로 검증합니다.
  • 오류 메시지가 민감 정보를 노출하지 않습니다.

3. SQL 인젝션 방지

FAIL: 절대 SQL을 문자열로 연결하지 마세요

// 위험함 - SQL 인젝션 취약점
const query = `SELECT * FROM users WHERE email = '${userEmail}'`
await db.query(query)

PASS: 항상 파라미터화된 쿼리를 사용하세요

// 안전함 - 파라미터화된 쿼리
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('email', userEmail)

// 또는 raw SQL 사용 시
await db.query(
  'SELECT * FROM users WHERE email = $1',
  [userEmail]
)

검증 단계

  • 모든 데이터베이스 쿼리는 파라미터화된 쿼리를 사용합니다.
  • SQL에 문자열 연결이 사용되지 않습니다.
  • ORM/쿼리 빌더가 올바르게 사용됩니다.
  • Supabase 쿼리가 적절히 이스케이프 처리됩니다.

4. 인증 및 권한 부여

JWT 토큰 처리

// FAIL: 잘못된 방법 - localStorage (XSS에 취약)
localStorage.setItem('token', token)

// PASS: 올바른 방법 - httpOnly 쿠키
res.setHeader('Set-Cookie',
  `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)

권한 확인

async function deleteUser(userId: string, requesterId: string) {
  // 항상 먼저 권한 확인
  const requester = await db.users.findUnique({
    where: { id: requesterId }
  })

  if (requester.role !== 'admin') {
    return NextResponse.json(
      { error: '권한이 없습니다.' },
      { status: 403 }
    )
  }

  // 삭제 진행
  await db.users.delete({ where: { id: userId } })
}

행 수준 보안 (Supabase)

-- 모든 테이블에 RLS 활성화
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

-- 사용자는 자신의 데이터만 조회 가능
CREATE POLICY "사용자 자신의 데이터 조회"
  ON users FOR SELECT
  USING (auth.uid() = id);

-- 사용자는 자신의 데이터만 업데이트 가능
CREATE POLICY "사용자 자신의 데이터 업데이트"
  ON users FOR UPDATE
  USING (auth.uid() = id);

검증 단계

  • 토큰은 httpOnly 쿠키에 저장됩니다 (localStorage 사용 안 함).
  • 민감한 작업 전에 권한 확인이 수행됩니다.
  • Supabase에서 행 수준 보안이 활성화됩니다.
  • 역할 기반 접근 제어가 구현됩니다.
  • 세션 관리가 안전합니다.

5. XSS 방지

HTML 살균

import DOMPurify from 'isomorphic-dompurify'

// 사용자가 제공한 HTML은 항상 살균
function renderUserContent(html: string) {
  const clean = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
    ALLOWED_ATTR: []
  })
  return <div dangerouslySetInnerHTML={{ __html: clean }} />
}

콘텐츠 보안 정책 (CSP)

엄격하게 시작하고 문서화된 제거 계획이 있을 때만 완화하세요. 'unsafe-inline' 또는 'unsafe-eval'을 기본값으로 사용하지 마세요. 이는 CSP 보호의 대부분을 무력화시키며 일시적인 호환성 부채로 처리해야 합니다.

// next.config.js
const securityHeaders = [
  {
    key: 'Content-Security-Policy',
    value: `
      default-src 'self';
      base-uri 'self';
      object-src 'none';
      frame-ancestors 'none';
      script-src 'self';
      style-src 'self';
      img-src 'self' data: https:;
      font-src 'self';
      connect-src 'self' https://api.example.com;
    `.replace(/\s{2,}/g, ' ').trim()
  }
]

검증 단계

  • 사용자가 제공한 HTML이 살균됩니다.
  • CSP 헤더가 구성됩니다.
  • 검증되지 않은 동적 콘텐츠가 렌더링되지 않습니다.
  • React의 내장 XSS 보호 기능이 사용됩니다.

6. CSRF 보호

CSRF 토큰

import { csrf } from '@/lib/csrf'

async function POST(request: Request) {
  const token = request.headers.get('X-CSRF-Token')

  if (!csrf.verify(token)) {
    return NextResponse.json(
      { error: '잘못된 CSRF 토큰입니다.' },
      { status: 403 }
    )
  }

  // 요청 처리
}

SameSite 쿠키

res.setHeader('Set-Cookie',
  `session=${sessionId}; HttpOnly; Secure; SameSite=Strict`)

검증 단계

  • 상태 변경 작업에 CSRF 토큰이 사용됩니다.
  • 모든 쿠키에 SameSite=Strict가 설정됩니다.
  • 이중 제출 쿠키 패턴이 구현됩니다.

7. 속도 제한

API 속도 제한

import rateLimit from 'express-rate-limit'

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15분
  max: 100, // 창당 100개 요청
  message: '너무 많은 요청이 있습니다.'
})

// 라우트에 적용
app.use('/api/', limiter)

비용이 많이 드는 작업

// 검색에 대한 공격적인 속도 제한
const searchLimiter = rateLimit({
  windowMs: 60 * 1000, // 1분
  max: 10, // 분당 10개 요청
  message: '너무 많은 검색 요청이 있습니다.'
})

app.use('/api/search', searchLimiter)

검증 단계

  • 모든 API 엔드포인트에 속도 제한이 적용됩니다.
  • 비용이 많이 드는 작업에는 더 엄격한 제한이 적용됩니다.
  • IP 기반 속도 제한이 구현됩니다.
  • 사용자 기반 속도 제한 (인증됨)이 구현됩니다.

8. 민감 데이터 노출

로깅

// FAIL: 잘못된 방법 - 민감 데이터 로깅
console.log('사용자 로그인:', { email, password })
console.log('결제:', { cardNumber, cvv })

// PASS: 올바른 방법 - 민감 데이터 마스킹
console.log('사용자 로그인:', { email, userId })
console.log('결제:', { last4: card.last4, userId })

오류 메시지

// FAIL: 잘못된 방법 - 내부 세부 정보 노출
catch (error) {
  return NextResponse.json(
    { error: error.message, stack: error.stack },
    { status: 500 }
  )
}

// PASS: 올바른 방법 - 일반 오류 메시지
catch (error) {
  console.error('내부 오류:', error)
  return NextResponse.json(
    { error: '오류가 발생했습니다. 다시 시도해 주세요.' },
    { status: 500 }
  )
}

검증 단계

  • 로그에 비밀번호, 토큰 또는 시크릿이 포함되지 않습니다.
  • 사용자용 오류 메시지는 일반적입니다.
  • 상세 오류는 서버 로그에만 기록됩니다.
  • 스택 트레이스가 사용자에게 노출되지 않습니다.

9. 블록체인 보안 (Solana)

지갑 확인

import { verify } from '@solana/web3.js'

async function verifyWalletOwnership(
  publicKey: string,
  signature: string,
  message: string
) {
  try {
    const isValid = verify(
      Buffer.from(message),
      Buffer.from(signature, 'base64'),
      Buffer.from(publicKey, 'base64')
    )
    return isValid
  } catch (error) {
    return false
  }
}

트랜잭션 확인

async function verifyTransaction(transaction: Transaction) {
  // 수신자 확인
  if (transaction.to !== expectedRecipient) {
    throw new Error('잘못된 수신자입니다.')
  }

  // 금액 확인
  if (transaction.amount > maxAmount) {
    throw new Error('금액이 한도를 초과했습니다.')
  }

  // 잔액 확인
  const balance = await getBalance(transaction.from)
  if (balance < transaction.amount) {
    throw new Error('잔액이 부족합니다.')
  }

  return true
}

검증 단계

  • 지갑 서명이 확인됩니다.
  • 트랜잭션 세부 정보가 검증됩니다.
  • 트랜잭션 전 잔액 확인이 수행됩니다.
  • 블라인드 트랜잭션 서명이 없습니다.

10. 종속성 보안

정기 업데이트

# 취약점 확인
npm audit

# 자동 수정 가능한 문제 수정
npm audit fix

# 종속성 업데이트
npm update

# 오래된 패키지 확인
npm outdated

잠금 파일

# 항상 잠금 파일 커밋
git add package-lock.json

# CI/CD에서 재현 가능한 빌드를 위해 사용
npm ci  # npm install 대신

검증 단계

  • 종속성이 최신 상태입니다.
  • 알려진 취약점이 없습니다 (npm audit clean).
  • 잠금 파일이 커밋됩니다.
  • GitHub에서 Dependabot이 활성화되었습니다.
  • 정기적인 보안 업데이트가 수행됩니다.

보안 테스트

자동화된 보안 테스트

// 인증 테스트
test('인증 필요', async () => {
  const response = await fetch('/api/protected')
  expect(response.status).toBe(401)
})

// 권한 테스트
test('관리자 역할 필요', async () => {
  const response = await fetch('/api/admin', {
    headers: { Authorization: `Bearer ${userToken}` }
  })
  expect(response.status).toBe(403)
})

// 입력 검증 테스트
test('잘못된 입력 거부', async () => {
  const response = await fetch('/api/users', {
    method: 'POST',
    body: JSON.stringify({ email: 'not-an-email' })
  })
  expect(response.status).toBe(400)
})

// 속도 제한 테스트
test('속도 제한 적용', async () => {
  const requests = Array(101).fill(null).map(() =>
    fetch('/api/endpoint')
  )

  const responses = await Promise.all(requests)
  const tooManyRequests = responses.filter(r => r.status === 429)

  expect(tooManyRequests.length).toBeGreaterThan(0)
})

배포 전 보안 체크리스트

프로덕션에 배포하기 전에 다음을 확인하세요:

  • 시크릿: 하드코딩된 시크릿 없음, 모두 환경 변수에 저장
  • 입력 검증: 모든 사용자 입력 검증 완료
  • SQL 인젝션: 모든 쿼리가 파라미터화됨
  • XSS: 사용자 콘텐츠가 살균됨
  • CSRF: 보호 활성화
  • 인증: 올바른 토큰 처리
  • 권한 부여: 역할 확인 구현
  • 속도 제한: 모든 엔드포인트에 활성화
  • HTTPS: 프로덕션에서 강제 적용
  • 보안 헤더: CSP, X-Frame-Options 구성
  • 오류 처리: 오류에 민감 데이터 없음
  • 로깅: 로그에 민감 데이터 없음
  • 종속성: 최신 상태, 취약점 없음
  • 행 수준 보안: Supabase에서 활성화
  • CORS: 올바르게 구성
  • 파일 업로드: 검증 완료 (크기, 타입)
  • 지갑 서명: 확인 완료 (블록체인 사용 시)

리소스


기억하세요: 보안은 선택 사항이 아닙니다. 하나의 취약점이 전체 플랫폼을 위협할 수 있습니다. 의심스러우면 항상 안전한 쪽을 선택하세요.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

관련 스킬