Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/channinghe_komodo-ops.json
T

1 line
17 KiB
JSON

{"repo": "channinghe/komodo-ops", "files": {".githooks/check_secrets.py": {"013047f6973e0a18690be9b4c5ec9f38e351b7ce": {"t": 1785747469.0995827, "n": 8008, "h": "d1003f2d88440632", "c": "\"\"\"\nPre-commit secrets leak detection.\n\nReads unified diff from stdin, checks for:\n 1. Known API key prefixes\n 2. High-entropy strings\n 3. Private patterns from external config\n 4. Semantic secrets (secret-named keys with hardcoded values)\n\nExit 0 = clean, Exit 1 = issues found.\n\"\"\"\n\nimport math\n\n# import os\nimport re\nimport sys\nfrom collections import Counter\nfrom pathlib import Path\n\nHOOK_DIR = Path(__file__).resolve().parent\nPATTERNS_FILE = HOOK_DIR / \"secrets-patterns\"\n\nRED = \"\\033[0;31m\"\nCYAN = \"\\033[0;36m\"\nNC = \"\\033[0m\"\n\n# ── Module 1: Known secret prefixes ──────────────────────────\n\nKNOWN_PREFIXES = [\n (re.compile(r\"sk-proj-[a-zA-Z0-9]{20,}\"), \"OpenAI API Key\"),\n (re.compile(r\"sk-ant-[a-zA-Z0-9]{20,}\"), \"Anthropic API Key\"),\n (re.compile(r\"sk-[a-f0-9]{32,}\"), \"DeepSeek/Generic SK Key\"),\n (re.compile(r\"AIzaSy[a-zA-Z0-9_-]{33}\"), \"Google API Key\"),\n (re.compile(r\"ghp_[a-zA-Z0-9]{36}\"), \"GitHub Personal Access Token\"),\n (re.compile(r\"gho_[a-zA-Z0-9]{36}\"), \"GitHub OAuth Token\"),\n (re.compile(r\"ghs_[a-zA-Z0-9]{36}\"), \"GitHub App Token\"),\n (re.compile(r\"glpat-[a-zA-Z0-9_-]{20,}\"), \"GitLab Personal Access Token\"),\n (re.compile(r\"xox[baprs]-[a-zA-Z0-9-]{10,}\"), \"Slack Token\"),\n (re.compile(r\"AKIA[0-9A-Z]{16}\"), \"AWS Access Key ID\"),\n (re.compile(r\"whsec_[a-zA-Z0-9]{32,}\"), \"Stripe Webhook Secret\"),\n (re.compile(r\"sk_live_[a-zA-Z0-9]{24,}\"), \"Stripe Live Key\"),\n]\n\n# ── Module 4: Semantic secret key names ──────────────────────\n\nSECRET_KEY_RE = re.compile(\n r\"[A-Z_]*(\"\n r\"PASSWORD|PASSWD|SECRET|TOKEN|API_KEY|PRIVATE_KEY|ACCESS_KEY|\"\n r\"AUTH_KEY|ENCRYPTION_KEY|SIGNING_KEY|JWT_SECRET|DB_PASS|REDIS_PASS\"\n r\")[A-Z_]*\",\n)\n\n# Variable reference patterns (safe to allow)\nVAR_REF_RE = re.compile(r\"^\\$\\{|^\\$[A-Z_]|^\\[\\[\")\n\n# Value extractor: after = or : , optionally quoted\nVALUE_AFTER_EQ = re.compile(r\"\"\"=\\s*['\"]?([^'\"#\\s].*?)['\"]?\\s*(?:#.*)?$\"\"\")\nVALUE_AFTER_COLON = re.compile(r\"\"\":\\s+['\"]?([^'\"#\\s].*?)['\"]?\\s*(?:#.*)?$\"\"\")\n\n# High-entropy value candidate: alphanumeric + base64 chars, ≥24 long\nENTROPY_CANDIDATE_RE = re.compile(r\"\"\"[=:]\\s*['\"]?([a-zA-Z0-9+/=_-]{24,})['\"]?\"\"\")\n\n# Config file extensions worth scanning for entropy / semantic checks\nCONFIG_EXTS = {\".yaml\", \".yml\", \".toml\", \".env\", \".conf\"}\n\n\ndef shannon_entropy(s: str) -> float:\n if len(s) < 16:\n return 0.0\n freq = Counter(s)\n length = len(s)\n return -sum((c / length) * math.log2(c / length) for c in freq.values())\n\n\ndef is_var_ref(val: str) -> bool:\n return bool(VAR_REF_RE.match(val))\n\n\ndef load_private_patterns() -> list[re.Pattern]:\n if not PATTERNS_FILE.is_file():\n return []\n patterns = []\n for line in PATTERNS_FILE.read_text().splitlines():\n line = line.strip()\n if not line or line.startswith(\"#\"):\n continue\n try:\n patterns.append(re.compile(line))\n except re.error:\n pass\n return patterns\n\n\ndef report(module: str, filepath: str, detail: str) -> None:\n print(f\"{RED}[BLOCKED]{NC} {CYAN}[{module}]{NC} {filepath}\")\n print(f\" → {detail}\")\n\n\ndef parse_diff(diff_text: str):\n \"\"\"Yield (filepath, added_line_content) for each added line in the diff.\"\"\"\n current_file = \"\"\n for line in diff_text.splitlines():\n m = re.match(r\"^diff --git a/(.*?) b/\", line)\n if m:\n current_file = m.group(1)\n continue\n if not line.startswith(\"+\") or line.startswith(\"+++\"):\n continue\n yield current_file, line[1:]\n\n\ndef ext_of(filepath: str) -> str:\n # Handle compound extensions like compose.env\n if filepath.endswith(\".env\"):\n return \".env\"\n return Path(filepath).suffix\n\n\ndef main() -> int:\n diff_text = sys.stdin.read()\n if not diff_text.strip():\n print(\"No staged changes to check.\")\n return 0\n\n private_patterns = load_private_patterns()\n issues = 0\n\n for filepath, content in parse_diff(diff_text):\n stripped = content.lstrip()\n\n # Skip comments\n if stripped.startswith(\"#\") or stripped.startswith(\"//\"):\n continue\n\n ext = ext_of(filepath)\n\n # ── Module 1: Known prefixes ──\n for pattern, desc in KNOWN_PREFIXES:\n if pattern.search(content):\n report(\"secret-prefix\", filepath, f\"Detected {desc} pattern\")\n issues += 1\n\n # ── Module 3: Private patterns ──\n if not filepath.startswith(\".githooks/\"):\n for pat in private_patterns:\n if pat.search(content):\n report(\n \"private-pattern\",\n filepath,\n f\"Matched private pattern: {pat.pattern}\",\n )\n issues += 1\n break\n\n # Only do config-aware checks on relevant file types\n if ext not in CONFIG_EXTS:\n continue\n\n # ── Module 2: High-entropy detection ──\n m = ENTROPY_CANDIDATE_RE.search(content)\n if m:\n val = m.group(1)\n if not is_var_ref(val) and \"/\" not in val:\n ent = shannon_entropy(val)\n if ent > 4.0:\n report(\n \"high-entropy\",\n filepath,\n f\"High entropy value ({ent:.2f} bits): {val[:12]}...\",\n )\n issues += 1\n\n # ── Module 4: Semantic secret detection ──\n if ext == \".env\":\n # KEY=VALUE format\n eq_pos = content.find(\"=\")\n if eq_pos > 0:\n key_part = (\n content[:eq_pos].strip().split()[-1]\n if content[:eq_pos].strip()\n else \"\"\n )\n if SECRET_KEY_RE.search(key_part):\n val = content[eq_pos + 1 :].strip().strip(\"'\\\"\")\n if val and not is_var_ref(val):\n report(\n \"semantic-secret\",\n filepath,\n f\"Hardcoded secret: {key_part}=<redacted>\",\n )\n issues += 1\n\n elif ext in (\".yaml\", \".yml\"):\n if SECRET_KEY_RE.search(content):\n val = None\n m_eq = VALUE_AFTER_EQ.search(content)\n m_col = VALUE_AFTER_COLON.search(content)\n if m_eq:\n val = m_eq.group(1).strip(\"'\\\"\")\n elif m_col:\n val = m_col.group(1).strip(\"'\\\"\")\n if val and not is_var_ref(val):\n # Extract key name for reporting\n km = SECRET_KEY_RE.search(content)\n key = km.group(0) if km else \"<key>\"\n report(\n \"semantic-secret\",\n filepath,\n f\"Hardcoded secret in YAML: {key}=<redacted>\",\n )\n issues += 1\n\n elif ext == \".toml\":\n m_toml = re.match(r'^value\\s*=\\s*\"(.+)\"', stripped)\n if m_toml:\n val = m_toml.group(1)\n if not is_var_ref(val) and len(val) >= 20:\n ent = shannon_entropy(val)\n if ent > 3.5:\n report(\n \"semantic-secret\",\n filepath,\n f\"Suspicious TOML value ({ent:.2f} bits entropy): {val[:8]}...\",\n )\n issues += 1\n\n return issues\n\n\nif __name__ == \"__main__\":\n print(\"=== Pre-commit: secrets leak detection ===\")\n issues = main()\n print()\n if issues > 0:\n print(\n f\"{RED}✗ Blocked: {issues} issue(s) found. Fix them or use --no-verify to bypass (not recommended).{NC}\"\n )\n sys.exit(1)\n else:\n print(\"✓ No secrets detected. Commit allowed.\")\n sys.exit(0)\n"}, "e65b3bf3f9ed635d0660cbd77f344f9ee044dcb8": {"t": 1785773479.4025724, "n": 8008, "h": "d1003f2d88440632", "c": "\"\"\"\nPre-commit secrets leak detection.\n\nReads unified diff from stdin, checks for:\n 1. Known API key prefixes\n 2. High-entropy strings\n 3. Private patterns from external config\n 4. Semantic secrets (secret-named keys with hardcoded values)\n\nExit 0 = clean, Exit 1 = issues found.\n\"\"\"\n\nimport math\n\n# import os\nimport re\nimport sys\nfrom collections import Counter\nfrom pathlib import Path\n\nHOOK_DIR = Path(__file__).resolve().parent\nPATTERNS_FILE = HOOK_DIR / \"secrets-patterns\"\n\nRED = \"\\033[0;31m\"\nCYAN = \"\\033[0;36m\"\nNC = \"\\033[0m\"\n\n# ── Module 1: Known secret prefixes ──────────────────────────\n\nKNOWN_PREFIXES = [\n (re.compile(r\"sk-proj-[a-zA-Z0-9]{20,}\"), \"OpenAI API Key\"),\n (re.compile(r\"sk-ant-[a-zA-Z0-9]{20,}\"), \"Anthropic API Key\"),\n (re.compile(r\"sk-[a-f0-9]{32,}\"), \"DeepSeek/Generic SK Key\"),\n (re.compile(r\"AIzaSy[a-zA-Z0-9_-]{33}\"), \"Google API Key\"),\n (re.compile(r\"ghp_[a-zA-Z0-9]{36}\"), \"GitHub Personal Access Token\"),\n (re.compile(r\"gho_[a-zA-Z0-9]{36}\"), \"GitHub OAuth Token\"),\n (re.compile(r\"ghs_[a-zA-Z0-9]{36}\"), \"GitHub App Token\"),\n (re.compile(r\"glpat-[a-zA-Z0-9_-]{20,}\"), \"GitLab Personal Access Token\"),\n (re.compile(r\"xox[baprs]-[a-zA-Z0-9-]{10,}\"), \"Slack Token\"),\n (re.compile(r\"AKIA[0-9A-Z]{16}\"), \"AWS Access Key ID\"),\n (re.compile(r\"whsec_[a-zA-Z0-9]{32,}\"), \"Stripe Webhook Secret\"),\n (re.compile(r\"sk_live_[a-zA-Z0-9]{24,}\"), \"Stripe Live Key\"),\n]\n\n# ── Module 4: Semantic secret key names ──────────────────────\n\nSECRET_KEY_RE = re.compile(\n r\"[A-Z_]*(\"\n r\"PASSWORD|PASSWD|SECRET|TOKEN|API_KEY|PRIVATE_KEY|ACCESS_KEY|\"\n r\"AUTH_KEY|ENCRYPTION_KEY|SIGNING_KEY|JWT_SECRET|DB_PASS|REDIS_PASS\"\n r\")[A-Z_]*\",\n)\n\n# Variable reference patterns (safe to allow)\nVAR_REF_RE = re.compile(r\"^\\$\\{|^\\$[A-Z_]|^\\[\\[\")\n\n# Value extractor: after = or : , optionally quoted\nVALUE_AFTER_EQ = re.compile(r\"\"\"=\\s*['\"]?([^'\"#\\s].*?)['\"]?\\s*(?:#.*)?$\"\"\")\nVALUE_AFTER_COLON = re.compile(r\"\"\":\\s+['\"]?([^'\"#\\s].*?)['\"]?\\s*(?:#.*)?$\"\"\")\n\n# High-entropy value candidate: alphanumeric + base64 chars, ≥24 long\nENTROPY_CANDIDATE_RE = re.compile(r\"\"\"[=:]\\s*['\"]?([a-zA-Z0-9+/=_-]{24,})['\"]?\"\"\")\n\n# Config file extensions worth scanning for entropy / semantic checks\nCONFIG_EXTS = {\".yaml\", \".yml\", \".toml\", \".env\", \".conf\"}\n\n\ndef shannon_entropy(s: str) -> float:\n if len(s) < 16:\n return 0.0\n freq = Counter(s)\n length = len(s)\n return -sum((c / length) * math.log2(c / length) for c in freq.values())\n\n\ndef is_var_ref(val: str) -> bool:\n return bool(VAR_REF_RE.match(val))\n\n\ndef load_private_patterns() -> list[re.Pattern]:\n if not PATTERNS_FILE.is_file():\n return []\n patterns = []\n for line in PATTERNS_FILE.read_text().splitlines():\n line = line.strip()\n if not line or line.startswith(\"#\"):\n continue\n try:\n patterns.append(re.compile(line))\n except re.error:\n pass\n return patterns\n\n\ndef report(module: str, filepath: str, detail: str) -> None:\n print(f\"{RED}[BLOCKED]{NC} {CYAN}[{module}]{NC} {filepath}\")\n print(f\" → {detail}\")\n\n\ndef parse_diff(diff_text: str):\n \"\"\"Yield (filepath, added_line_content) for each added line in the diff.\"\"\"\n current_file = \"\"\n for line in diff_text.splitlines():\n m = re.match(r\"^diff --git a/(.*?) b/\", line)\n if m:\n current_file = m.group(1)\n continue\n if not line.startswith(\"+\") or line.startswith(\"+++\"):\n continue\n yield current_file, line[1:]\n\n\ndef ext_of(filepath: str) -> str:\n # Handle compound extensions like compose.env\n if filepath.endswith(\".env\"):\n return \".env\"\n return Path(filepath).suffix\n\n\ndef main() -> int:\n diff_text = sys.stdin.read()\n if not diff_text.strip():\n print(\"No staged changes to check.\")\n return 0\n\n private_patterns = load_private_patterns()\n issues = 0\n\n for filepath, content in parse_diff(diff_text):\n stripped = content.lstrip()\n\n # Skip comments\n if stripped.startswith(\"#\") or stripped.startswith(\"//\"):\n continue\n\n ext = ext_of(filepath)\n\n # ── Module 1: Known prefixes ──\n for pattern, desc in KNOWN_PREFIXES:\n if pattern.search(content):\n report(\"secret-prefix\", filepath, f\"Detected {desc} pattern\")\n issues += 1\n\n # ── Module 3: Private patterns ──\n if not filepath.startswith(\".githooks/\"):\n for pat in private_patterns:\n if pat.search(content):\n report(\n \"private-pattern\",\n filepath,\n f\"Matched private pattern: {pat.pattern}\",\n )\n issues += 1\n break\n\n # Only do config-aware checks on relevant file types\n if ext not in CONFIG_EXTS:\n continue\n\n # ── Module 2: High-entropy detection ──\n m = ENTROPY_CANDIDATE_RE.search(content)\n if m:\n val = m.group(1)\n if not is_var_ref(val) and \"/\" not in val:\n ent = shannon_entropy(val)\n if ent > 4.0:\n report(\n \"high-entropy\",\n filepath,\n f\"High entropy value ({ent:.2f} bits): {val[:12]}...\",\n )\n issues += 1\n\n # ── Module 4: Semantic secret detection ──\n if ext == \".env\":\n # KEY=VALUE format\n eq_pos = content.find(\"=\")\n if eq_pos > 0:\n key_part = (\n content[:eq_pos].strip().split()[-1]\n if content[:eq_pos].strip()\n else \"\"\n )\n if SECRET_KEY_RE.search(key_part):\n val = content[eq_pos + 1 :].strip().strip(\"'\\\"\")\n if val and not is_var_ref(val):\n report(\n \"semantic-secret\",\n filepath,\n f\"Hardcoded secret: {key_part}=<redacted>\",\n )\n issues += 1\n\n elif ext in (\".yaml\", \".yml\"):\n if SECRET_KEY_RE.search(content):\n val = None\n m_eq = VALUE_AFTER_EQ.search(content)\n m_col = VALUE_AFTER_COLON.search(content)\n if m_eq:\n val = m_eq.group(1).strip(\"'\\\"\")\n elif m_col:\n val = m_col.group(1).strip(\"'\\\"\")\n if val and not is_var_ref(val):\n # Extract key name for reporting\n km = SECRET_KEY_RE.search(content)\n key = km.group(0) if km else \"<key>\"\n report(\n \"semantic-secret\",\n filepath,\n f\"Hardcoded secret in YAML: {key}=<redacted>\",\n )\n issues += 1\n\n elif ext == \".toml\":\n m_toml = re.match(r'^value\\s*=\\s*\"(.+)\"', stripped)\n if m_toml:\n val = m_toml.group(1)\n if not is_var_ref(val) and len(val) >= 20:\n ent = shannon_entropy(val)\n if ent > 3.5:\n report(\n \"semantic-secret\",\n filepath,\n f\"Suspicious TOML value ({ent:.2f} bits entropy): {val[:8]}...\",\n )\n issues += 1\n\n return issues\n\n\nif __name__ == \"__main__\":\n print(\"=== Pre-commit: secrets leak detection ===\")\n issues = main()\n print()\n if issues > 0:\n print(\n f\"{RED}✗ Blocked: {issues} issue(s) found. Fix them or use --no-verify to bypass (not recommended).{NC}\"\n )\n sys.exit(1)\n else:\n print(\"✓ No secrets detected. Commit allowed.\")\n sys.exit(0)\n"}}}}