Communitygithub.com

security-review

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

security-review란 무엇인가요?

이 스킬은 소프트웨어 개발 과정에서 코드가 보안 모범 사례를 따르도록 보장하고 잠재적인 취약점을 식별하는 데 도움을 줍니다. 주로 AI 어시스턴트(Claude Code, Cursor 등)와 함께 사용되며, 개발자가 인증, 사용자 입력, 비밀번호 관리, API 엔드포인트, 결제 기능, 민감 데이터 저장/전송, 타사 API 통합 등 보안에 민감한 작업을 수행할 때 활성화됩니다. 보안 리뷰 스킬은 10가지 주요 영역(비밀번호 관리, 입력 검증, SQL 인젝션 방지, 인증/권한 부여, XSS 방지, CSRF 보호, 속도 제한, 민감 데이터 노출 방지, 블록체인 보안(Solana), 종속성 보안)에 대한 상세한 체크리스트와 코드 예제(FAIL/PASS 패턴)를 제공합니다. 또한 자동화된 보안 테스트 예제와 배포 전 체크리스트를 포함하여 개발자가 실수하기 쉬운 부분을 사전에 방지하고 안전한 코드를 작성할 수 있도록 지원합니다.

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

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

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

문서

보안 리뷰 스킬

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

활성화 시점

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

보안 체크리스트

1. 비밀번호 관리

실패: 절대 이렇게 하지 마세요

const apiKey = "sk-proj-xxxxx"  // 하드코딩된 비밀번호
const dbPassword = "password123" // 소스 코드에 포함

통과: 항상 이렇게 하세요

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)
})

// 처리 전 검증
export async function createUser(input: unknown) {
  try {
    const validated = CreateUserSchema.parse(input)
    return await 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 인젝션 방지

실패: 절대 SQL을 연결하지 마세요

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

통과: 항상 매개변수화된 쿼리 사용

// 안전: 매개변수화된 쿼리
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('email', userEmail)

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

확인 단계

  • 모든 데이터베이스 쿼리에서 매개변수화된 쿼리 사용
  • SQL에 문자열 연결 없음
  • ORM/쿼리 빌더 올바르게 사용
  • Supabase 쿼리가 적절히 정리됨

4. 인증 및 권한 부여

JWT 토큰 처리

// 실패: 잘못됨: localStorage (XSS에 취약)
localStorage.setItem('token', token)

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

권한 부여 확인

export 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 }} />
}

콘텐츠 보안 정책

엄격하게 시작하고 문서화된 제거 계획이 있을 때만 완화하세요. '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'

export 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. 민감 데이터 노출

로깅

// 실패: 잘못됨: 민감 데이터 로깅
console.log('사용자 로그인:', { email, password })
console.log('결제:', { cardNumber, cvv })

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

오류 메시지

// 실패: 잘못됨: 내부 정보 노출
catch (error) {
  return NextResponse.json(
    { error: error.message, stack: error.stack },
    { status: 500 }
  )
}

// 통과: 올바름: 일반적인 오류 메시지
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/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

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.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

관련 스킬