Coverage for lintro / ai / secrets.py: 100%
13 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Detect potential secrets in code before sending to AI."""
3from __future__ import annotations
5import re
7# Common secret patterns
8_SECRET_PATTERNS = [
9 re.compile(
10 r"(?:api[_-]?key|apikey)\s*[=:]\s*[\"']?[A-Za-z0-9_\-]{20,}",
11 re.I,
12 ),
13 re.compile(
14 r"(?:secret|password|passwd|pwd)\s*[=:]\s*[\"']?[^\s\"']{8,}",
15 re.I,
16 ),
17 re.compile(
18 r"(?:token)\s*[=:]\s*[\"']?[A-Za-z0-9_\-\.]{20,}",
19 re.I,
20 ),
21 re.compile(
22 r"(?:aws_access_key_id|aws_secret_access_key)\s*[=:]\s*[\"']?[A-Za-z0-9/+=]{16,}",
23 re.I,
24 ),
25 re.compile(r"ghp_[A-Za-z0-9]{36}"), # GitHub personal access token
26 re.compile(r"sk-[A-Za-z0-9]{20,}"), # OpenAI/Anthropic API key
27 re.compile(
28 r"-----BEGIN (?:RSA |EC )?PRIVATE KEY-----"
29 r"[\s\S]*?"
30 r"-----END (?:RSA |EC )?PRIVATE KEY-----",
31 ),
32]
35def scan_for_secrets(text: str) -> list[str]:
36 """Return list of detected secret pattern descriptions.
38 Scans the given text against a set of common secret patterns
39 (API keys, passwords, tokens, private keys) and returns a
40 human-readable description for each match found.
42 Args:
43 text: The text to scan for secrets.
45 Returns:
46 List of description strings for each detected secret pattern.
47 """
48 found: list[str] = []
49 for pattern in _SECRET_PATTERNS:
50 if pattern.search(text):
51 found.append(f"Potential secret detected: {pattern.pattern[:40]}...")
52 return found
55def redact_secrets(text: str) -> str:
56 """Redact detected secrets from text.
58 Replaces all matches of known secret patterns with ``[REDACTED]``
59 to prevent accidental leakage when sending text to external AI
60 providers.
62 Args:
63 text: The text to redact secrets from.
65 Returns:
66 Text with all detected secrets replaced by ``[REDACTED]``.
67 """
68 for pattern in _SECRET_PATTERNS:
69 text = pattern.sub("[REDACTED]", text)
70 return text