#!/usr/bin/env python3 """Targeted xKiro key search on GitHub.""" import json, os, time, urllib.request, urllib.parse, re, sys token = os.environ.get("GH_TOKEN") or os.popen("gh auth token").read().strip() def gh_api(endpoint, params): url = f"https://api.github.com/{endpoint}?" + urllib.parse.urlencode(params) req = urllib.request.Request(url, headers={ "Authorization": f"token {token}", "Accept": "application/vnd.github+json", "User-Agent": "xkiro-hunter", }) try: with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read()), dict(resp.headers) except Exception as e: return None, {} queries = [ "sk-xt- extension:env", "sk-xt- extension:py", "sk-xt- extension:js", "sk-xt- extension:ts", "sk-xt- extension:sh", "sk-xt- extension:yaml", "sk-xt- extension:yml", "sk-xt- extension:json", "sk-xt- extension:toml", "sk-xt- extension:ipynb", "sk-xt- extension:cfg", "sk-xt- extension:ini", "sk-xt- extension:go", "sk-xt- extension:rs", "sk-xt- extension:rb", "sk-xt- extension:php", "sk-xt- extension:java", "sk-xt- extension:lua", "sk-xt- extension:tf", "sk-xt- extension:Dockerfile", "XKIRO_API_KEY extension:env", "XKIRO_API_KEY extension:py", "XKIRO_API_KEY extension:js", "XKIRO_API_KEY extension:ts", "XKIRO_KEY extension:env", "XKIRO_KEY extension:py", "api.xkiro.com extension:py", "api.xkiro.com extension:js", "api.xkiro.com extension:ts", "api.xkiro.com extension:env", "api.xkiro.com extension:yaml", "api.xkiro.com extension:json", "api.xkiro.com extension:ipynb", "api.xkiro.com extension:sh", "xkiro extension:py", "xkiro extension:js", "xkiro extension:env", "xkiro extension:json", "xkiro extension:yaml", "xkiro extension:md", "anthropic/claude-sonnet-4-5 extension:py", "anthropic/claude-sonnet-4-5 extension:js", "anthropic/claude-sonnet-4-5 extension:env", "anthropic/claude-opus-4-5 extension:py", "anthropic/claude-opus-4-5 extension:js", ] commit_queries = ["sk-xt-", "XKIRO_API_KEY", "api.xkiro.com"] pattern = re.compile(r"sk-xt-[a-f0-9]{40,}") all_candidates = {} total_found = 0 print(f"=== xKiro Search ({len(queries)} code + {len(commit_queries)} commit) ===\n", flush=True) for i, q in enumerate(queries, 1): data, headers = gh_api("search/code", {"q": q, "per_page": 100}) remaining = headers.get("X-RateLimit-Remaining", "?") if data is None: print(f" [{i}/{len(queries)}] ERR: {q}", flush=True) time.sleep(7) continue items = data.get("items", []) if items: print(f" [{i}/{len(queries)}] ({remaining}) {q} -> {len(items)} hits", flush=True) for item in items: url = item["html_url"] if url not in all_candidates: all_candidates[url] = { "repo": item["repository"]["full_name"], "path": item["path"], "url": url, } total_found += len(items) time.sleep(7) print(f"\nCode: {len(all_candidates)} unique files from {total_found} hits\n", flush=True) print("=== Commit Search ===", flush=True) for q in commit_queries: data, _ = gh_api("search/commits", {"q": q, "per_page": 50}) if data is None: print(f" ERR: {q}", flush=True) time.sleep(7) continue items = data.get("items", []) if items: print(f" {q} -> {len(items)} commits", flush=True) for item in items: url = item.get("html_url", "") if url and url not in all_candidates: all_candidates[url] = { "repo": item.get("repository", {}).get("full_name", ""), "path": "(commit)", "url": url, } time.sleep(7) print(f"\nTotal candidates: {len(all_candidates)}\n", flush=True) with open("results/xkiro_candidates.json", "w") as f: json.dump(list(all_candidates.values()), f, indent=2) print("=== Extracting Keys ===", flush=True) keys_found = set() def to_raw(url): return url.replace("github.com", "raw.githubusercontent.com").replace("/blob/", "/") for i, (url, info) in enumerate(sorted(all_candidates.items()), 1): raw_url = to_raw(url) req = urllib.request.Request(raw_url, headers={"User-Agent": "Mozilla/5.0"}) try: with urllib.request.urlopen(req, timeout=10) as resp: content = resp.read().decode("utf-8", errors="replace") except: continue matches = pattern.findall(content) if matches: keys_found.update(matches) print(f" [{i}/{len(all_candidates)}] {info['repo']:40s} {info['path'][:40]} -> {len(matches)} key(s)", flush=True) for k in matches: print(f" {k}", flush=True) if i % 50 == 0: print(f" [{i}/{len(all_candidates)}] fetched... {len(keys_found)} keys", flush=True) print(f"\n=== Results ===", flush=True) print(f"Candidates: {len(all_candidates)}", flush=True) print(f"Keys found: {len(keys_found)}", flush=True) if keys_found: with open("results/xkiro_keys.txt", "w") as f: for k in sorted(keys_found): f.write(k + "\n") print(f"\nSaved to results/xkiro_keys.txt\n", flush=True) for k in sorted(keys_found): print(f" {k}", flush=True) # Verify keys print("\n=== Verifying Keys ===", flush=True) for k in sorted(keys_found): req = urllib.request.Request( "https://api.xkiro.com/v1/models", headers={"Authorization": f"Bearer {k}", "User-Agent": "xkiro-hunter"}, ) try: with urllib.request.urlopen(req, timeout=15) as resp: code = resp.getcode() body = resp.read().decode()[:200] print(f" {k} -> HTTP {code} LIVE ✅", flush=True) except urllib.error.HTTPError as e: print(f" {k} -> HTTP {e.code} {e.read()[:100].decode(errors='replace')} ❌", flush=True) except Exception as e: print(f" {k} -> ERR {e} ❌", flush=True) else: print("No xKiro keys found.", flush=True)