---
title: "AI가 짜준 코드의 배신" — 바이브코딩 앱의 기술적 취약점 5가지
date: 2026-09-23
time: "23:20"
model: admin
category: knowhow
summary: 바이브코딩으로 만든 앱에 숨겨진 보안 취약점 5가지를 실제 코드 예시로 분석. 권한 검증 누락, SQL 인젝션, 취약한 라이브러리, 정보 노출, 그리고 실전 보안 체크리스트까지.
tags: 바이브코딩,보안,취약점,SQL인젝션,XSS,시큐어코딩,AI코딩
---
# AI가 짜준 코드의 배신 — 바이브코딩 앱의 기술적 취약점 5가지
"우와, 이게 프롬프트 한 줄로 구현됐다고?"
AI가 만들어준 코드를 보고 감탄한 순간, 당신은 아마 이런 생각을 했을 것이다. "이거 진짜 괜찮은데?" 그런데 그 코드 안에 당신의 사용자 데이터를 통째로 빼낼 수 있는 구멍이 뚫려 있을 가능성이 높다.
이 글에서는 바이브코딩으로 만든 앱에서 **가장 흔하고 치명적인 보안 취약점 5가지**를 실제 코드와 함께 정리한다.
## 1. 권한 검증 누락 (IDOR)
**AI가 만든 코드:**
```javascript
// Express.js — 주문 조회 API
app.get('/api/orders/:orderId', (req, res) => {
const orderId = req.params.orderId;
// 여기가 문제다:ใคร가 요청해도 모든 주문을 볼 수 있음
db.query('SELECT * FROM orders WHERE id = ?', [orderId], (err, result) => {
if (err) return res.status(500).json({ error: err.message });
res.json(result[0]);
});
});
```
**위험성:**
누군가 `/api/orders/1`, `/api/orders/2`, `/api/orders/3` 순서대로 요청하면 **다른 사용자의 주문 내역을 모두 열람**할 수 있다. 이것이 바로 IDOR(Insecure Direct Object Reference) 취약점이다.
**공격 시나리오:**
```
1. 내 주문 조회: GET /api/orders/42 → 정상
2. 타인 주문 조회: GET /api/orders/43 → 다른 사용자 결제 정보 노출
3. 루프로 반복: 1~1000번까지 순회 → 전체 사용자 데이터 유출
```
**바른 코드:**
```javascript
app.get('/api/orders/:orderId', authenticateToken, (req, res) => {
const orderId = req.params.orderId;
const userId = req.user.id; // JWT에서 추출한 현재 사용자 ID
db.query(
'SELECT * FROM orders WHERE id = ? AND user_id = ?',
[orderId, userId],
(err, result) => {
if (err) return res.status(500).json({ error: '서버 오류' });
if (!result.length) return res.status(404).json({ error: '주문 없음' });
res.json(result[0]);
}
);
});
```
**차이:** `AND user_id = ?` 조건 하나가 추가되었다. 현재 로그인한 사용자의 주문만 조회된다.
## 2. SQL 인젝션
**AI가 만든 코드:**
```python
# Flask — 검색 기능
@app.route('/search')
def search():
keyword = request.args.get('q')
# 직접 문자열 삽입 → 인젝션 취약
query = f"SELECT * FROM products WHERE name LIKE '%{keyword}%'"
cursor.execute(query)
results = cursor.fetchall()
return jsonify(results)
```
**공격 시나리오:**
```
정상 입력: http://app.com/search?q=노트북
→ SELECT * FROM products WHERE name LIKE '%노트북%'
악성 입력: http://app.com/search?q=' OR '1'='1
→ SELECT * FROM products WHERE name LIKE '%' OR '1'='1%'
→ 모든 상품 데이터 유출
더 악성: http://app.com/search?q='; DROP TABLE products;--
→ 테이블 자체가 삭제됨
```
**바른 코드:**
```python
@app.route('/search')
def search():
keyword = request.args.get('q')
# 바인딩 파라미터 사용 → 인젝션 방지
cursor.execute(
"SELECT * FROM products WHERE name LIKE %s",
(f'%{keyword}%',)
)
results = cursor.fetchall()
return jsonify(results)
```
**핵심:** `f-string` 대신 `?` 또는 `%s` 바인딩을 사용하면, 입력값이 SQL 구문이 아닌 "값"으로 처리된다.
## 3. XSS (Cross-Site Scripting)
**AI가 만든 코드:**
```html
```
**공격 시나리오:**
```
정상 URL: profile.html?user=홍길동
→ 홍길동의 프로필
(정상)
악성 URL: profile.html?user=
→ 사용자의 쿠키(세션 토큰)가 공격자 서버로 전송됨
→ 공격자가 세션을 탈취하여 로그인된 상태로 앱 사용
```
**바른 코드:**
```html
```
**핵심:** `innerHTML` 대신 `textContent`를 사용하면, 입력값이 HTML로 해석되지 않는다.
## 4. 민감 정보 하드코딩
**AI가 만든 코드:**
```python
# 데이터베이스 연결
import psycopg2
conn = psycopg2.connect(
host="db.mycompany.com",
database="production",
user="admin",
password="SuperSecret123!" # ← 여기
)
# 이메일 발송
SMTP_PASSWORD = "GmailAppPassword456" # ← 여기
# 결제 API
STRIPE_SECRET_KEY = "sk_live_4eC39HqLyjWDarjtT1zdp7dc" # ← 여기
```
**위험성:**
이 코드가 GitHub에 올라가면? 5분 안에 자동 스캔 봇이 이 키들을 찾아내어 사용한다. `sk_live_`로 시작하는 Stripe 키는 곧바로 결제 사기에 사용된다.
**실제 사고 사례:**
GitHub에서 `password`, `secret`, `api_key` 등을 스캔하는 자동화 봇이 24시간 돌아간다. 코드를 push하는 순간, 민감 정보는 이미 유출된 것이다.
**바른 코드:**
```python
# .env 파일 (GitHub에 올리지 않음)
# DB_PASSWORD=SuperSecret123!
# SMTP_PASSWORD=GmailAppPassword456
# STRIPE_SECRET_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc
import os
from dotenv import load_dotenv
load_dotenv()
conn = psycopg2.connect(
host=os.environ.get('DB_HOST'),
database=os.environ.get('DB_NAME'),
user=os.environ.get('DB_USER'),
password=os.environ.get('DB_PASSWORD')
)
```
**.gitignore에 반드시 추가:**
```
.env
*.key
*.pem
config/secrets.json
```
## 5. 에러 핸들링 미흡으로 인한 정보 노출
**AI가 만든 코드:**
```javascript
// Express.js — 전역 에러 핸들러
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
error: err.message,
stack: err.stack // ← 치명적
});
});
```
**위험성:**
운영 서버에서 에러가 발생하면, 사용자 브라우저에 다음과 같은 정보가 노출된다:
```json
{
"error": "Cannot read property 'id' of undefined",
"stack": "TypeError: Cannot read property 'id' of undefined\n
at /app/src/routes/orders.js:15:23\n
at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)\n
at /app/node_modules/express/lib/router/index.js:28:3\n
at Function.handle (/app/node_modules/express/lib/router/index.js:88:3)"
}
```
이 정보를 통해 공격자는:
- **서버 디렉터리 구조** 파악 (`/app/src/routes/orders.js`)
- **프레임워크 버전** 확인 (`express/lib/router`)
- **코드 라인 넘버** 추적 (`orders.js:15:23`)
- **추가 공격 설계** 가능
**바른 코드:**
```javascript
// 전역 에러 핸들러
app.use((err, req, res, next) => {
console.error(err.stack); // 서버 로그에만 기록
// 운영 환경: 상세 에러 노출 금지
if (process.env.NODE_ENV === 'production') {
res.status(500).json({ error: '서버 내부 오류가 발생했습니다.' });
} else {
// 개발 환경에서만 상세 에러 표시
res.status(500).json({ error: err.message, stack: err.stack });
}
});
```
## 6. 실전 보안 체크리스트
바이브코딩 앱을 프로덕션에 배포하기 전 반드시 확인하라:
### 백엔드
- [ ] **입력값 검증**: 모든 사용자 입력에 SQL 인젝션 필터링이 걸려 있는가?
- [ ] **인증과 인가**: 모든 API 요청에서 JWT/세션 토큰을 재검증하는가?
- [ ] **인젝션 방지**: SQL 쿼리에 바인딩 파라미터를 사용하는가?
- [ ] **에러 핸들링**: 운영 서버에서 상세 에러 메시지가 노출되지 않는가?
- [ ] **민감 정보 격리**: API 키, 비밀번호가 `.env`에 있고 `.gitignore`에 등록되어 있는가?
### 프론트엔드
- [ ] **XSS 방지**: `innerHTML` 대신 `textContent`를 사용하는가?
- [ ] **CSRF 보호**: POST/PUT/DELETE 요청에 CSRF 토큰이 포함되는가?
- [ ] **콘솔 로그 제거**: `console.log()`가 프로덕션 코드에 남아있지 않은가?
### 인프라
- [ ] **의존성 감사**: `npm audit` 또는 `pip check`로 취약한 라이브러리가 없는가?
- [ ] **HTTPS 적용**: 모든 통신이 HTTPS로 암호화되는가?
- [ ] **디버그 모드 OFF**: `DEBUG=True`가 프로덕션 환경에서 켜져있지 않은가?
```bash
# npm 의존성 감사
npm audit
npm audit fix
# pip 의존성 감사
pip check
pip-audit
# SonarQube 정적 분석 (예시)
sonar-scanner -Dsonar.projectKey=myapp -Dsonar.sources=./src
```
## 7. 결론 — 지휘관이 똑똑해야 군대가 안전하다
AI는 훌륭한 코딩 도구다. 그러나 AI는 보안을 "책임지지" 않는다. AI가 만든 코드의 보안은 **전적으로 사용자의 몫**이다.
> **"AI가 만든 코드는 범죄에 악용되기 딱 좋은 수준으로 완벽하게 보안 취약하다."**
SQL 인젝션이 뭔지 모르면, AI가 만들어준 검색 기능이 전체 데이터베이스를 유출할 수 있다. XSS가 뭔지 모르면, AI가 만들어준 프로필 페이지가 사용자 세션을 탈취당할 수 있다.
바이브코딩을 한다면, 적어도 **이 다섯 가지 취약점이 뭔지, 왜 위험한지, 어떻게 고치는지**는 알아야 한다. 그렇지 않으면 당신이 만든 앱은 당신의 사용자를 배신하게 된다.
> **"지휘관(인간)이 똑똑해야 군대(AI)가 안전하다."**
---
*본 글은 운영자 개인의 실전 경험과 관점을 바탕으로 작성되었습니다.*