github-guardian 1.0.1__tar.gz → 1.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {github_guardian-1.0.1 → github_guardian-1.0.3}/PKG-INFO +1 -1
- {github_guardian-1.0.1 → github_guardian-1.0.3}/core/scanner.py +49 -7
- {github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/PKG-INFO +1 -1
- {github_guardian-1.0.1 → github_guardian-1.0.3}/setup.py +1 -1
- {github_guardian-1.0.1 → github_guardian-1.0.3}/core/__init__.py +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/core/hook.py +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/core/remote.py +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/SOURCES.txt +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/dependency_links.txt +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/entry_points.txt +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/requires.txt +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/top_level.txt +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/guardian.py +0 -0
- {github_guardian-1.0.1 → github_guardian-1.0.3}/setup.cfg +0 -0
|
@@ -1,17 +1,47 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
+
import math
|
|
3
4
|
from rich.table import Table
|
|
4
5
|
|
|
5
|
-
#
|
|
6
|
+
# Robust set of enterprise-grade patterns
|
|
6
7
|
SECRET_PATTERNS = {
|
|
7
|
-
"AWS Access Key": r'AKIA[0-9A-Z]{16}',
|
|
8
|
-
"
|
|
8
|
+
"AWS Access Key ID": r'AKIA[0-9A-Z]{16}',
|
|
9
|
+
"AWS Secret Key": r'(?i)aws_secret_access_key\s*[:=]\s*["\']?([A-Za-z0-9/+=]{40})["\']?',
|
|
10
|
+
"GitHub Token": r'gh[pousr]_[0-9a-zA-Z]{36}|github_pat_[0-9a-zA-Z]{82}',
|
|
9
11
|
"Slack Webhook": r'https://hooks\.slack\.com/services/T[0-9A-Z]{8}/B[0-9A-Z]{8}/[0-9a-zA-Z]{24}',
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"Google API Key": r'AIza[0-9A-Za-z\-_]{35}'
|
|
12
|
+
"Slack Token": r'xox[bapr]-[0-9a-zA-Z]{10,48}',
|
|
13
|
+
"Stripe API Key": r'[rs]k_(?:live|test)_[0-9a-zA-Z]{24,32}',
|
|
14
|
+
"Google API Key": r'AIza[0-9A-Za-z\-_]{35}',
|
|
15
|
+
"OpenAI API Key": r'sk-[a-zA-Z0-9]{20,}|sk\s*-\s*[a-zA-Z0-9\-_]{40,}',
|
|
16
|
+
"Twilio Account SID": r'AC[0-9a-fA-F]{32}',
|
|
17
|
+
"Twilio Auth Token": r'(?i)twilio_auth_token\s*[:=]\s*["\']?([0-9a-fA-F]{32})["\']?',
|
|
18
|
+
"Discord Webhook": r'https://discord(?:app)?\.com/api/webhooks/[0-9]+/[0-9a-zA-Z_-]+',
|
|
19
|
+
"Discord Bot Token": r'[MN][A-Za-z0-9_]{23}\.[A-Za-z0-9_]{6}\.[A-Za-z0-9_]{27}',
|
|
20
|
+
"Telegram Bot Token": r'[0-9]{9,10}:[a-zA-Z0-9_-]{35}',
|
|
21
|
+
"Heroku API Key": r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}',
|
|
22
|
+
"Mailgun API Key": r'key-[0-9a-zA-Z]{32}',
|
|
23
|
+
"SendGrid API Key": r'SG\.[0-9a-zA-Z_-]{22}\.[0-9a-zA-Z_-]{43}',
|
|
24
|
+
"Facebook Access Token": r'EAACEdEose0c[0-9A-Za-z]+',
|
|
25
|
+
"Database URL": r'(?:mongodb(?:\+srv)?|postgres|postgresql|mysql|mssql|redis):\/\/[^:\s]+:[^@\s]+@[^@\s]+',
|
|
26
|
+
"Private Key": r'-----BEGIN (?:RSA|OPENSSH|DSA|EC|PGP)? PRIVATE KEY-----',
|
|
27
|
+
"JWT": r'eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+',
|
|
28
|
+
"NPM Token": r'npm_[0-9a-zA-Z]{36}'
|
|
13
29
|
}
|
|
14
30
|
|
|
31
|
+
GENERIC_ASSIGNMENT_PATTERN = re.compile(
|
|
32
|
+
r"(?i)\b['\"]?([a-z0-9_\-\.]*(?:key|secret|token|password|passwd|pw|auth|cred|pass|db|uri|url)[a-z0-9_\-\.]*)['\"]?\s*[:=]\s*['\"]([a-zA-Z0-9_\-\.\/\+=]{16,})['\"]"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def calculate_entropy(s: str) -> float:
|
|
36
|
+
if not s:
|
|
37
|
+
return 0.0
|
|
38
|
+
entropy = 0.0
|
|
39
|
+
for x in range(256):
|
|
40
|
+
p_x = float(s.count(chr(x))) / len(s)
|
|
41
|
+
if p_x > 0:
|
|
42
|
+
entropy += - p_x * math.log(p_x, 2)
|
|
43
|
+
return entropy
|
|
44
|
+
|
|
15
45
|
SAST_PATTERNS = {
|
|
16
46
|
"SQL Injection (Raw Query)": r"\.execute\(\".*%\s*\"",
|
|
17
47
|
"Insecure Rendering (XSS)": r"dangerouslySetInnerHTML",
|
|
@@ -36,7 +66,8 @@ def run_local_scan(path: str, console, hook_mode: bool = False) -> bool:
|
|
|
36
66
|
|
|
37
67
|
for root, _, files in os.walk(path):
|
|
38
68
|
# Ignore common build/dependency directories
|
|
39
|
-
|
|
69
|
+
split_dirs = root.split(os.sep)
|
|
70
|
+
if any(x in split_dirs for x in [".git", "node_modules", "venv", ".venv", "build_env", "dist", "build", "__pycache__"]):
|
|
40
71
|
continue
|
|
41
72
|
for file in files:
|
|
42
73
|
ext = os.path.splitext(file)[1]
|
|
@@ -54,9 +85,20 @@ def run_local_scan(path: str, console, hook_mode: bool = False) -> bool:
|
|
|
54
85
|
|
|
55
86
|
for line_idx, line in enumerate(lines, 1):
|
|
56
87
|
# Check for Secrets
|
|
88
|
+
matched_any = False
|
|
57
89
|
for name, pat in SECRET_PATTERNS.items():
|
|
58
90
|
if re.search(pat, line):
|
|
59
91
|
findings.append((filepath, line_idx, "SECRET LEAK", name))
|
|
92
|
+
matched_any = True
|
|
93
|
+
|
|
94
|
+
# If no specific patterns matched, check for generic high-entropy assignments
|
|
95
|
+
if not matched_any:
|
|
96
|
+
gen_match = GENERIC_ASSIGNMENT_PATTERN.search(line)
|
|
97
|
+
if gen_match:
|
|
98
|
+
val = gen_match.group(2)
|
|
99
|
+
# Only alert if value has high entropy
|
|
100
|
+
if calculate_entropy(val) >= 3.2:
|
|
101
|
+
findings.append((filepath, line_idx, "SECRET LEAK", f"High-Entropy Secret ({gen_match.group(1)})"))
|
|
60
102
|
|
|
61
103
|
# Check for Semantic vulnerabilities
|
|
62
104
|
for name, pat in SAST_PATTERNS.items():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_guardian-1.0.1 → github_guardian-1.0.3}/github_guardian.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|