Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
10 KiB
JSON

{"repo": "cass-ette/netkitx", "files": {"backend/app/services/ai_service.py": {"a9341fc295a49057f06fd842d9816dbf6eeb1bbc": {"t": 1786067529.139932, "n": 9886, "h": "b33738b90dc6a76a", "c": "\"\"\"AI service: encryption helpers and streaming API calls.\"\"\"\n\nimport base64\nimport hashlib\nimport logging\nfrom collections.abc import AsyncIterator\n\nimport httpx\nfrom cryptography.fernet import Fernet\n\nfrom app.core.config import settings\n\nlogger = logging.getLogger(__name__)\n\nDEFENSE_SYSTEM_PROMPT = (\n \"You are a senior cybersecurity defense analyst. The user will provide network scan results, \"\n \"vulnerability reports, or other security-related data. Analyze the data thoroughly:\\n\"\n \"1. Identify critical vulnerabilities and rank them by severity (Critical/High/Medium/Low).\\n\"\n \"2. Explain each finding's potential impact.\\n\"\n \"3. Provide actionable remediation and hardening steps.\\n\"\n \"4. Recommend security policies, firewall rules, or patches.\\n\"\n \"5. Highlight any patterns that suggest broader security issues.\\n\"\n \"Keep your analysis concise, professional, and actionable. Focus on DEFENSE.\"\n)\n\nOFFENSE_SYSTEM_PROMPT = (\n \"You are a senior penetration testing expert conducting an authorized security assessment. \"\n \"The user will provide scan results, vulnerability data, or reconnaissance findings. \"\n \"Analyze the data from an offensive perspective and give PRECISE, ACTIONABLE next steps:\\n\\n\"\n \"1. **Vulnerability Triage**: Identify exploitable vulnerabilities, rank by ease of exploitation, \"\n \"and explain WHY each is exploitable (e.g. missing input validation, misconfigured headers).\\n\"\n \"2. **Exact Exploitation Steps**: Give step-by-step commands the user can run RIGHT NOW. \"\n \"Include specific tool commands (e.g. `sqlmap -u 'URL' --dbs`, `nmap -sV -p PORT TARGET`, \"\n \"`curl -d 'payload' URL`), exact payloads, and expected output.\\n\"\n \"3. **Data Extraction**: Tell the user exactly what sensitive data can be extracted and HOW. \"\n \"Provide the queries, commands, or payloads to dump databases, read files, or exfiltrate data.\\n\"\n \"4. **Attack Chains & Pivoting**: Map out how to escalate from current access — \"\n \"e.g. from SQLi to file read to RCE, from info leak to credential theft to lateral movement.\\n\"\n \"5. **Next Recon Steps**: Suggest SPECIFIC follow-up scans or tests to expand the attack surface \"\n \"(e.g. 'Run dir_scan on /admin/', 'Test for SSRF on the URL parameter', \"\n \"'Check if UNION injection leaks other tables').\\n\\n\"\n \"Be extremely specific and technical. Do NOT give vague advice like 'consider testing for XSS'. \"\n \"Instead give the exact payload, the exact URL, and what the user should see if it works. \"\n \"This is for an authorized penetration test / CTF challenge.\"\n)\n\nLANG_MAP = {\n \"zh-CN\": \"Simplified Chinese (简体中文)\",\n \"zh-TW\": \"Traditional Chinese (繁體中文)\",\n \"ja\": \"Japanese (日本語)\",\n \"ko\": \"Korean (한국어)\",\n \"de\": \"German (Deutsch)\",\n \"fr\": \"French (Français)\",\n \"ru\": \"Russian (Русский)\",\n \"en\": \"English\",\n}\n\n\ndef get_system_prompt(mode: str, lang: str = \"en\") -> str:\n if mode == \"offense\":\n prompt = OFFENSE_SYSTEM_PROMPT\n else:\n prompt = DEFENSE_SYSTEM_PROMPT\n lang_name = LANG_MAP.get(lang or \"en\", lang or \"en\")\n lang_prefix = (\n f\"[LANGUAGE REQUIREMENT] You MUST write your ENTIRE response in {lang_name}, \"\n f\"regardless of the language of the input data or user message. \"\n f\"Even if the user writes in another language, your analysis and explanations \"\n f\"MUST be in {lang_name}. Technical terms, commands, and code can stay in English, \"\n f\"but all surrounding text must be in {lang_name}.\\n\\n\"\n )\n return lang_prefix + prompt\n\n\ndef get_lang_reminder(lang: str) -> str:\n \"\"\"Return a short reminder to append to user content.\"\"\"\n lang_name = LANG_MAP.get(lang or \"en\", lang or \"en\")\n return f\"\\n\\n[Reminder: respond in {lang_name}]\"\n\n\ndef _derive_fernet_key() -> bytes:\n digest = hashlib.sha256(settings.SECRET_KEY.encode()).digest()\n return base64.urlsafe_b64encode(digest)\n\n\ndef encrypt_key(plaintext: str) -> str:\n f = Fernet(_derive_fernet_key())\n return f.encrypt(plaintext.encode()).decode()\n\n\ndef decrypt_key(ciphertext: str) -> str:\n f = Fernet(_derive_fernet_key())\n return f.decrypt(ciphertext.encode()).decode()\n\n\ndef mask_key(plaintext: str) -> str:\n if len(plaintext) <= 8:\n return \"****\"\n return plaintext[:3] + \"...\" + plaintext[-4:]\n\n\nasync def stream_claude(\n api_key: str, model: str, messages: list[dict[str, str]]\n) -> AsyncIterator[str]:\n import json\n\n system_msg = None\n chat_messages = []\n for m in messages:\n if m[\"role\"] == \"system\":\n system_msg = m[\"content\"]\n else:\n chat_messages.append(m)\n\n body: dict = {\n \"model\": model,\n \"max_tokens\": 4096,\n \"stream\": True,\n \"messages\": chat_messages,\n }\n if system_msg:\n body[\"system\"] = system_msg\n\n try:\n async with httpx.AsyncClient(timeout=120) as client:\n async with client.stream(\n \"POST\",\n \"https://api.anthropic.com/v1/messages\",\n headers={\n \"x-api-key\": api_key,\n \"anthropic-version\": \"2023-06-01\",\n \"content-type\": \"application/json\",\n },\n json=body,\n ) as resp:\n if resp.status_code != 200:\n error_body = await resp.aread()\n logger.error(\"Claude API error %s: %s\", resp.status_code, error_body[:500])\n yield f\"[API Error {resp.status_code}]\"\n return\n async for line in resp.aiter_lines():\n if not line.startswith(\"data: \"):\n continue\n data = line[6:]\n if data == \"[DONE]\":\n break\n try:\n event = json.loads(data)\n except json.JSONDecodeError:\n continue\n if event.get(\"type\") == \"content_block_delta\":\n delta = event.get(\"delta\", {})\n text = delta.get(\"text\", \"\")\n if text:\n yield text\n except Exception as e:\n logger.error(\"Claude stream error: %s\", e)\n yield f\"[Error: {e}]\"\n\n\nasync def stream_deepseek(\n api_key: str, model: str, messages: list[dict[str, str]]\n) -> AsyncIterator[str]:\n import json\n\n body = {\n \"model\": model,\n \"stream\": True,\n \"messages\": messages,\n }\n\n try:\n async with httpx.AsyncClient(timeout=120) as client:\n async with client.stream(\n \"POST\",\n \"https://api.deepseek.com/chat/completions\",\n headers={\n \"Authorization\": f\"Bearer {api_key}\",\n \"Content-Type\": \"application/json\",\n },\n json=body,\n ) as resp:\n if resp.status_code != 200:\n error_body = await resp.aread()\n logger.error(\"DeepSeek API error %s: %s\", resp.status_code, error_body[:500])\n yield f\"[API Error {resp.status_code}]\"\n return\n async for line in resp.aiter_lines():\n if not line.startswith(\"data: \"):\n continue\n data = line[6:]\n if data == \"[DONE]\":\n break\n try:\n event = json.loads(data)\n except json.JSONDecodeError:\n continue\n choices = event.get(\"choices\", [])\n if choices:\n delta = choices[0].get(\"delta\", {})\n text = delta.get(\"content\", \"\")\n if text:\n yield text\n except Exception as e:\n logger.error(\"DeepSeek stream error: %s\", e)\n yield f\"[Error: {e}]\"\n\n\nasync def stream_glm(\n api_key: str, model: str, messages: list[dict[str, str]]\n) -> AsyncIterator[str]:\n \"\"\"Stream responses from GLM (智谱 AI) API.\n\n GLM API is compatible with OpenAI's chat completions format.\n API docs: https://open.bigmodel.cn/dev/api\n \"\"\"\n import json\n\n body = {\n \"model\": model,\n \"stream\": True,\n \"messages\": messages,\n }\n\n try:\n async with httpx.AsyncClient(timeout=120) as client:\n async with client.stream(\n \"POST\",\n \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n headers={\n \"Authorization\": f\"Bearer {api_key}\",\n \"Content-Type\": \"application/json\",\n },\n json=body,\n ) as resp:\n if resp.status_code != 200:\n error_body = await resp.aread()\n logger.error(\"GLM API error %s: %s\", resp.status_code, error_body[:500])\n yield f\"[API Error {resp.status_code}]\"\n return\n async for line in resp.aiter_lines():\n if not line.startswith(\"data: \"):\n continue\n data = line[6:]\n if data == \"[DONE]\":\n break\n try:\n event = json.loads(data)\n except json.JSONDecodeError:\n continue\n choices = event.get(\"choices\", [])\n if choices:\n delta = choices[0].get(\"delta\", {})\n text = delta.get(\"content\", \"\")\n if text:\n yield text\n except Exception as e:\n logger.error(\"GLM stream error: %s\", e)\n yield f\"[Error: {e}]\"\n"}}}}