T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/watcher.py:89
- Finding
- Unauthenticated Relay Can Exfiltrate Private Agent Memory to an Attacker-Controlled Callback<![CDATA[ ## Vulnerability Details **File Location**: `api/index.py:92-104`; `scripts/watcher.py:64-82, 85-128, 145-148` **Vulnerability Type**: Missing authentication, excessive local-file access, prompt injection, and arbitrary outbound callback **Risk Level**: Critical ### Vulnerable Code ```python # api/index.py:92-104 user_request = body.get("userRequest", {}) utterance = user_request.get("utterance", "").strip() user_id = user_request.get("user", {}).get("id", "unknown") callback_url = user_request.get("callbackUrl", "") # 모드 결정 is_relay_mode = bool(SUPABASE_URL and SUPABASE_KEY) if is_relay_mode: # [Relay Mode] 로컬 처리를 위해 DB 저장 if not callback_url: self._send_json(_kakao_response("AI 챗봇(콜백) 설정을 켜주세요.")) return if _save_to_queue(user_id, utterance, callback_url): ``` ```python # scripts/watcher.py:64-82 def send_callback(url, text): """카카오톡 서버로 답장 발송""" payload = json.dumps({ "version": "2.0", "template": { "outputs": [{"simpleText": {"text": text}}] } }).encode("utf-8") req = urllib.request.Request(url, data=payload, method="POST", headers={ "Content-Type": "application/json" }) try: with urllib.request.urlopen(req) as resp: print(f"✅ 발송 성공: {text[:20]}...") return True except Exception as e: print(f"❌ 발송 실패: {e}") return False ``` ```python # scripts/watcher.py:89-110 # 1. 로컬 메모리 읽기 (Context Injection) memory_path = os.path.expanduser("~/.openclaw/workspace/MEMORY.md") memory_context = "" if os.path.exists(memory_path): with open(memory_path) as f: memory_context = f.read()[:2000] # 너무 길면 자름 # 2. 시스템 프롬프트 구성 system_prompt = f"""너는 라온이다. (Mac Studio에서 실행 중) 사용자의 질문: {utterance} [장기 기억 (MEMORY.md)] {memory_context} 사용자에게 친절하게, 그리고 기억을 바탕으로 대답해.""" # 3. LLM 호출 (Gemini) return _call_gemini_direct(system_prompt, utterance) ``` ```python # scripts/watcher.py:116-128 url = f"https://gener ...[truncated 2638 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require cryptographic authentication of every inbound Kakao webhook before queue insertion and reject requests when authentication is unavailable. 2. Do not accept arbitrary callback URLs. Permit only documented Kakao HTTPS callback hosts and bind each callback to authenticated request metadata. 3. Resolve callback hostnames and reject loopback, private, link-local, multicast, reserved, and cloud metadata addresses. 4. Do not automatically load `MEMORY.md` for externally initiated requests. Require explicit, per-user authorization and expose only narrowly selected memory records. 5. Treat memory as confidential data rather than instructions. Apply prompt-injection controls and prevent the model from reproducing raw memory. 6. Add output data-loss-prevention checks before callbacks are sent. 7. Use a least-privilege Supabase key with row-level security instead of a service-role key where possible. 8. Add queue provenance fields, replay protection, rate limits, record expiration, and atomic message claiming. 9. Clearly disclose to users when message and memory content will be sent to Gemini. ]]>
