--- 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)가 안전하다."** --- *본 글은 운영자 개인의 실전 경험과 관점을 바탕으로 작성되었습니다.*