← 블로그 목록
AI 보안코드 검증SQL 인젝션프로덕션취약점

AI 생성 코드 프로덕션 투입 전 반드시 확인할 보안 체크리스트 7가지

AI 생성 코드의 SQL 인젝션, XSS, 시크릿 노출 등 보안 취약점을 프로덕션 투입 전 점검하는 7가지 체크리스트와 자동 검증 방법을 코드 예시로 정리했습니다.

Vibeollio 팀-

ChatGPT, Claude, GitHub Copilot 같은 AI 코드 생성 도구는 개발 속도를 높이지만, 생성된 코드가 항상 보안 기준을 만족하지는 않습니다. 특히 SQL 인젝션, XSS, 하드코딩된 시크릿 같은 취약점이 의도치 않게 포함될 수 있습니다. 프로덕션 환경에 배포하기 전에 체계적인 보안 검증이 필수입니다.

1. SQL 인젝션 취약점 점검

AI 생성 코드에서 가장 흔한 실수는 사용자 입력을 직접 쿼리에 연결하는 것입니다.

위험한 코드 예시:

# ❌ 위험: 직접 문자열 연결
user_id = request.args.get('id')
query = f"SELECT * FROM users WHERE id = {user_id}"
result = db.execute(query)

사용자가 id=1 OR 1=1 같은 값을 입력하면 모든 사용자 데이터가 노출됩니다.

안전한 코드:

# ✅ 안전: 파라미터화된 쿼리 사용
user_id = request.args.get('id')
query = "SELECT * FROM users WHERE id = ?"
result = db.execute(query, (user_id,))

자동 점검 방법:

  • bandit (Python): bandit -r . | grep sql
  • SonarQube: 정적 분석으로 쿼리 패턴 감지
  • SQLMap: 실제 SQL 인젝션 테스트

2. XSS(Cross-Site Scripting) 방어 확인

AI는 HTML 템플릿에서 사용자 데이터를 이스케이프하지 않은 채로 렌더링하곤 합니다.

위험한 코드:

<!-- ❌ 위험: 사용자 입력이 그대로 렌더링 -->
<div>{{ user_comment }}</div>

사용자가 <script>alert('hacked')</script>를 댓글로 입력하면 모든 방문자의 브라우저에서 실행됩니다.

안전한 코드:

<!-- ✅ 안전: 자동 이스케이프 -->
<div>{{ user_comment | escape }}</div>

<!-- 또는 Vue/React 사용 -->
<div>{userComment}</div> {/* 기본 이스케이프 */}

자동 점검:

  • npm audit: JavaScript 의존성 취약점 검사
  • OWASP ZAP: 동적 XSS 스캔
  • 린터 설정: ESLint의 no-v-html 규칙

3. 하드코딩된 시크릿(API 키, 비밀번호) 탐지

AI는 예제 코드에서 실제 시크릿을 포함시킬 수 있습니다.

위험한 코드:

# ❌ 위험: 코드에 API 키 노출
API_KEY = "sk-1234567890abcdef"
db_password = "admin123"

response = requests.get(
    "https://api.example.com/data",
    headers={"Authorization": f"Bearer {API_KEY}"}
)

Git 히스토리에 남으면 누구나 접근할 수 있습니다.

안전한 코드:

# ✅ 안전: 환경 변수 사용
import os
from dotenv import load_dotenv

load_dotenv()
API_KEY = os.getenv("API_KEY")
db_password = os.getenv("DB_PASSWORD")

if not API_KEY:
    raise ValueError("API_KEY 환경 변수가 설정되지 않았습니다")

.env 파일:

API_KEY=sk-1234567890abcdef
DB_PASSWORD=admin123

.gitignore:

.env
*.pem
*.key

자동 점검:

  • truffleHog: Git 히스토리에서 시크릿 스캔
  • detect-secrets: 코드베이스 내 시크릿 탐지
  • git-secrets: 커밋 전 시크릿 차단

4. CORS(Cross-Origin Resource Sharing) 설정 검증

AI 생성 백엔드 코드는 CORS를 너무 개방적으로 설정하곤 합니다.

위험한 코드:

# ❌ 위험: 모든 도메인 허용
from flask_cors import CORS

app = Flask(__name__)
CORS(app)  # 모든 출처에서 요청 허용

이 설정은 Origin: *로 응답해 CSRF 공격에 취약합니다.

안전한 코드:

# ✅ 안전: 특정 도메인만 허용
from flask_cors import CORS

app = Flask(__name__)

CORS(app, resources={
    r"/api/*": {
        "origins": ["https://trusted-domain.com"],
        "methods": ["GET", "POST"],
        "allow_headers": ["Content-Type"],
        "supports_credentials": True
    }
})

자동 점검:

  • 코드 리뷰: CORS 설정이 명시적으로 정의되었는지 확인
  • 브라우저 개발자 도구: Network 탭에서 Access-Control-Allow-Origin 헤더 검증

5. 인증 및 인가 우회 확인

AI는 인증 로직을 간단하게 생성해 우회 가능한 상태로 남길 수 있습니다.

위험한 코드:

# ❌ 위험: 클라이언트 토큰 검증 없음
@app.route('/admin/delete', methods=['POST'])
def delete_user():
    user_id = request.json.get('user_id')
    # 인증 확인 없이 바로 삭제
    db.delete_user(user_id)
    return {"status": "deleted"}

누구나 이 엔드포인트로 요청을 보내 데이터를 삭제할 수 있습니다.

안전한 코드:

from functools import wraps
import jwt

def require_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = request.headers.get('Authorization')
        if not token:
            return {"error": "Unauthorized"}, 401
        
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
            if payload.get('role') != 'admin':
                return {"error": "Forbidden"}, 403
        except jwt.InvalidTokenError:
            return {"error": "Invalid token"}, 401
        
        return f(*args, **kwargs)
    return decorated

@app.route('/admin/delete', methods=['POST'])
@require_auth
def delete_user():
    user_id = request.json.get('user_id')
    db.delete_user(user_id)
    return {"status": "deleted"}

자동 점검:

  • OWASP ZAP: 인증 우회 시뮬레이션
  • 코드 리뷰: 모든 보호된 엔드포인트에 @require_auth 데코레이터 확인

6. 의존성 취약점 스캔

AI가 추천한 라이브러리 버전에 알려진 취약점이 있을 수 있습니다.

확인 방법:

# Python
pip install safety
safety check

# Node.js
npm audit
npm audit fix

# Ruby
bundle audit check --update

예시 출력:

┌─────────────────────────────────────────────┐
│ Django 3.0.0 has known vulnerability CVE... │
│ Update to 3.2.5 or later                   │
└─────────────────────────────────────────────┘

7. 입력 검증 및 레이트 제한

AI 코드는 사용자 입력을 충분히 검증하지 않거나 브루트포스 공격을 방어하지 않을 수 있습니다.

위험한 코드:

# ❌ 위험: 입력 길이 제한 없음
@app.route('/search')
def search():
    query = request.args.get('q')
    results = db.search(query)  # 매우 긴 쿼리로 DoS 가능
    return results

안전한 코드:

from flask_limiter import Limiter
from marshmallow import Schema, fields, ValidationError

limiter = Limiter(app, key_func=lambda: request.remote_addr)

class SearchSchema(Schema):
    q = fields.Str(required=True, validate=lambda x: len(x) <= 100)

@app.route('/search')
@limiter.limit("30 per minute")  # 분당 30회 제한
def search():
    try:
        args = SearchSchema().load(request.args)
    except ValidationError as err:
        return {"error": err.messages}, 400
    
    results = db.search(args['q'])
    return results

AI 코드 보안 검증 자동화 파이프라인

프로덕션 배포 전 이 체크리스트를 CI/CD에 통합하면 효과적입니다:

# .github/workflows/security-check.yml
name: Security Checks
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run Bandit (Python)
        run: pip install bandit && bandit -r . -f json -o bandit-report.json
      
      - name: Run Safety (Dependencies)
        run: pip install safety && safety check --json
      
      - name: Scan Secrets
        run: pip install detect-secrets && detect-secrets scan
      
      - name: OWASP Dependency Check
        uses: dependency-check/Dependency-Check_Action@main

이 파이프라인은 커밋할 때마다 자동으로 보안 취약점을 검사합니다.

Vibeollio에서 AI 보안 프로젝트 공유하기

AI 생성 코드의 보안 검증 자동화 도구나 보안 감시 솔루션을 개발 중이라면 Vibeollio에 프로젝트를 등록해 더 많은 개발자에게 알릴 수 있습니다. 보안 취약점 탐지 스크립트, 정책 템플릿, 또는 AI 코드 감시 서비스 등을 공유하면 커뮤니티 피드백을 받고 사용자를 확보할 수 있습니다.