fix(security): CRITICAL 보안 이슈 13건 일괄 수정
- SEC-42: JWT algorithm HS256 명시 (sign 5곳, verify 3곳) - SEC-44: MariaDB/PhpMyAdmin 포트 127.0.0.1 바인딩 - SEC-29: escHtml = escapeHtml alias 추가 (XSS 방지) - SEC-39: Python Dockerfile 4개 non-root user + chown - SEC-43: deploy-remote.sh 삭제 (평문 비밀번호 포함) - SEC-11,12: SQL SET ? → 명시적 컬럼 whitelist + IN절 parameterized - QA-34: vacation approveRequest/cancelRequest 트랜잭션 래핑 - SEC-32,34: material_comparison.py 5개 엔드포인트 인증 + confirmed_by - SEC-33: files.py 17개 미인증 엔드포인트 인증 추가 - SEC-37: chatbot 프롬프트 인젝션 방어 (sanitize + XML 구분자) - SEC-38: fastapi-bridge 프록시 JWT 검증 + 캐시 키 user_id 포함 - SEC-58/QA-98: monthly-comparison API_BASE_URL 수정 + 401 처리 - SEC-61: monthlyComparisonModel SELECT FOR UPDATE 추가 - SEC-63: proxyInputController 에러 메시지 노출 제거 - QA-103: pageAccessRoutes error→message 통일 - SEC-62: tbm-create onclick 인젝션 → data-attribute event delegation - QA-99: tbm-mobile/create 캐시 버스팅 갱신 - QA-100,101: ESC 키 리스너 cleanup 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,13 @@ import json
|
||||
from services.ollama_client import ollama_client
|
||||
|
||||
|
||||
def sanitize_user_input(text: str, max_length: int = 500) -> str:
|
||||
"""사용자 입력 길이 제한 및 정리"""
|
||||
if not text:
|
||||
return ""
|
||||
return str(text)[:max_length].strip()
|
||||
|
||||
|
||||
ANALYZE_SYSTEM_PROMPT = """당신은 공장 현장 신고 접수를 도와주는 AI 도우미입니다.
|
||||
사용자가 현장에서 발견한 문제를 설명하면, 아래 카테고리 목록을 참고하여 가장 적합한 신고 유형과 카테고리를 제안해야 합니다.
|
||||
|
||||
@@ -35,10 +42,12 @@ async def analyze_user_input(user_text: str, categories: dict) -> dict:
|
||||
cat_names = [f" - ID {c['id']}: {c['name']}" for c in cats]
|
||||
category_context += f"\n[{type_label} ({type_key})]\n" + "\n".join(cat_names) + "\n"
|
||||
|
||||
safe_text = sanitize_user_input(user_text)
|
||||
prompt = f"""카테고리 목록:
|
||||
{category_context}
|
||||
|
||||
사용자 입력: "{user_text}"
|
||||
사용자 입력:
|
||||
<user_input>{safe_text}</user_input>
|
||||
|
||||
위 카테고리 목록을 참고하여 JSON으로 응답하세요."""
|
||||
|
||||
@@ -71,12 +80,14 @@ async def analyze_user_input(user_text: str, categories: dict) -> dict:
|
||||
async def summarize_report(data: dict) -> dict:
|
||||
"""최종 신고 내용을 요약"""
|
||||
prompt = f"""신고 정보:
|
||||
- 설명: {data.get('description', '')}
|
||||
- 유형: {data.get('type', '')}
|
||||
- 카테고리: {data.get('category', '')}
|
||||
- 항목: {data.get('item', '')}
|
||||
- 위치: {data.get('location', '')}
|
||||
- 프로젝트: {data.get('project', '')}
|
||||
<user_input>
|
||||
- 설명: {sanitize_user_input(data.get('description', ''))}
|
||||
- 유형: {sanitize_user_input(data.get('type', ''))}
|
||||
- 카테고리: {sanitize_user_input(data.get('category', ''))}
|
||||
- 항목: {sanitize_user_input(data.get('item', ''))}
|
||||
- 위치: {sanitize_user_input(data.get('location', ''))}
|
||||
- 프로젝트: {sanitize_user_input(data.get('project', ''))}
|
||||
</user_input>
|
||||
|
||||
위 정보를 보기 좋게 요약하여 JSON으로 응답하세요."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user