-
Notifications
You must be signed in to change notification settings - Fork 0
139 lines (124 loc) · 4.7 KB
/
Copy pathsecurity.yml
File metadata and controls
139 lines (124 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
name: Security Review
on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
schedule:
- cron: "0 3 * * 1" # Weekly Monday 3am UTC
jobs:
security:
name: Security Scan
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install security tools
run: |
pip install bandit safety pip-audit 2>/dev/null || pip install bandit safety
- name: Bandit — static code security analysis
run: |
bandit -r tooldns/ \
--skip B101,B603,B604,B607 \
--format txt \
--severity-level medium \
--confidence-level medium \
-o bandit-report.txt || true
cat bandit-report.txt
# Fail on HIGH severity issues
bandit -r tooldns/ \
--skip B101,B603,B604,B607 \
--severity-level high \
--confidence-level high \
--exit-zero
- name: Safety — check for known CVEs in dependencies
run: |
pip install -e . 2>/dev/null || true
safety check --full-report || true
- name: Check for hardcoded secrets
run: |
echo "Scanning for hardcoded API keys and tokens..."
FOUND=0
# Patterns that look like real secrets (not examples/placeholders)
if grep -rn \
-e 'api_key\s*=\s*"[a-zA-Z0-9_\-]\{20,\}"' \
-e 'token\s*=\s*"[a-zA-Z0-9_\-]\{20,\}"' \
-e 'secret\s*=\s*"[a-zA-Z0-9_\-]\{20,\}"' \
-e 'password\s*=\s*"[a-zA-Z0-9_\-]\{8,\}"' \
--include="*.py" --include="*.json" --include="*.yaml" \
--exclude-dir=".git" \
. | grep -v "example\|placeholder\|your_\|YOUR_\|test_\|fake_\|dummy\|<\|>"; then
FOUND=1
fi
if [ "$FOUND" -eq 1 ]; then
echo "WARNING: Possible hardcoded secrets found above. Review carefully."
else
echo "No obvious hardcoded secrets found."
fi
- name: Check .env files are not committed
run: |
if git ls-files | grep -E "^\.env$|^\.env\.local$|^\.env\.production$"; then
echo "ERROR: .env file is committed to the repo — remove it immediately!"
exit 1
fi
echo ".env check passed — no secrets in repo"
- name: Check API key masking (never expose keys in responses)
run: |
python3 -c "
import re, glob, sys
issues = []
# Scan Python source for patterns that might return raw API keys in responses
for f in glob.glob('tooldns/**/*.py', recursive=True):
content = open(f).read()
# Flag if full key is returned in a JSON response dict (not just logged)
if re.search(r'['\''\"]\s*key\s*[''\"].*credentials\.credentials', content):
issues.append(f'{f}: possible raw key exposure in response')
if issues:
print('API KEY EXPOSURE ISSUES:')
for i in issues: print(' ', i)
sys.exit(1)
print('API key masking check passed')
"
- name: Check for SQL injection risks
run: |
python3 -c "
import re, glob, sys
issues = []
for f in glob.glob('tooldns/**/*.py', recursive=True):
content = open(f).read()
# Flag f-string SQL queries (risk of injection)
matches = re.findall(r'f[\"\'](.*?SELECT.*?WHERE.*?)[\"\']\s*[,)]', content, re.IGNORECASE)
for m in matches:
if '{' in m:
issues.append(f'{f}: possible SQL injection: {m[:80]}')
if issues:
print('SQL INJECTION RISKS:')
for i in issues: print(' ', i)
# Warn only, don't fail (could be false positives)
else:
print('SQL injection check passed')
"
- name: Check CORS and auth middleware
run: |
python3 -c "
content = open('main.py').read()
issues = []
if 'allow_origins=[\"*\"]' in content or \"allow_origins=['*']\" in content:
issues.append('CORS allows ALL origins — restrict in production')
if issues:
print('SECURITY WARNINGS:')
for i in issues: print(' -', i)
else:
print('CORS/auth check passed')
"
- name: Upload Bandit report
uses: actions/upload-artifact@v7
if: always()
with:
name: bandit-security-report
path: bandit-report.txt
retention-days: 30