diff --git a/src/codex_plugin_scanner/checks/security.py b/src/codex_plugin_scanner/checks/security.py index b720ff5fd..630670e18 100644 --- a/src/codex_plugin_scanner/checks/security.py +++ b/src/codex_plugin_scanner/checks/security.py @@ -5,38 +5,114 @@ import ipaddress import json import re +from dataclasses import dataclass +from itertools import pairwise from pathlib import Path from urllib.parse import urlparse from ..models import CheckResult, Finding, Severity from ..path_support import resolves_within_root + +@dataclass(frozen=True, slots=True) +class SecretPattern: + pattern: re.Pattern[str] + kind: str = "provider" + value_group: int = 0 + + # Patterns for hardcoded secrets -SECRET_PATTERNS: list[re.Pattern[str]] = [ - re.compile(r"AKIA[0-9A-Z]{16}"), # AWS access key - re.compile(r"aws_secret_access_key\s*[=:]\s*[\"']?[A-Za-z0-9/+=]{40}", re.I), - re.compile(r"-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----"), - re.compile(r"password\s*[=:]\s*[\"'][^\s\"']{8,}", re.I), - re.compile(r"secret\s*[=:]\s*[\"'][^\s\"']{8,}", re.I), - re.compile(r"token\s*[=:]\s*[\"'][^\s\"']{8,}", re.I), - re.compile(r"api_?key\s*[=:]\s*[\"'][^\s\"']{8,}", re.I), - re.compile(r"API_KEY\s*[=:]\s*[\"'][^\s\"']{8,}"), - re.compile(r"PRIVATE_KEY\s*[=:]\s*[\"'][^\s\"']{8,}"), - re.compile(r"ghp_[A-Za-z0-9]{36}"), # GitHub PAT - re.compile(r"gho_[A-Za-z0-9]{36}"), # GitHub OAuth - re.compile(r"ghu_[A-Za-z0-9]{36}"), # GitHub user token - re.compile(r"ghs_[A-Za-z0-9]{36}"), # GitHub app token - re.compile(r"github_pat_[A-Za-z0-9_]{20,}"), # GitHub fine-grained PAT - re.compile(r"glpat-[A-Za-z0-9\-]{20}"), # GitLab PAT - re.compile(r"xox[bpas]-[A-Za-z0-9\-]{10,}"), # Slack tokens - re.compile(r"xoxe-[A-Za-z0-9\-]{10,}"), # Slack user tokens - re.compile(r"xoxr-[A-Za-z0-9\-]{10,}"), # Slack configuration tokens - re.compile(r"xapp-[A-Za-z0-9\-]{10,}"), # Slack app-level tokens - re.compile(r"sk-(?:proj-|ant-)?[A-Za-z0-9_-]{20,}"), # OpenAI / Anthropic keys -] +SECRET_PATTERNS: tuple[SecretPattern, ...] = ( + SecretPattern(re.compile(r"AKIA[0-9A-Z]{16}")), + SecretPattern(re.compile(r"aws_secret_access_key\s*[=:]\s*[\"']?([A-Za-z0-9/+=]{40})", re.I), value_group=1), + SecretPattern( + re.compile( + r"-----BEGIN (?P