1+ #! /bin/bash
2+ # Dependency Security Check Script
3+ # Comprehensive security audit for Python dependencies
4+
5+ set -euo pipefail
6+
7+ # Colors for output
8+ RED=' \033[0;31m'
9+ GREEN=' \033[0;32m'
10+ YELLOW=' \033[1;33m'
11+ BLUE=' \033[0;34m'
12+ NC=' \033[0m' # No Color
13+
14+ # Script configuration
15+ SCRIPT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " && pwd) "
16+ PROJECT_ROOT=" $( cd " ${SCRIPT_DIR} /.." && pwd) "
17+ LOG_FILE=" ${PROJECT_ROOT} /dependency_audit.log"
18+
19+ # Function to print colored output
20+ print_status () {
21+ echo -e " ${BLUE} [INFO]${NC} $1 "
22+ }
23+
24+ print_warning () {
25+ echo -e " ${YELLOW} [WARNING]${NC} $1 "
26+ }
27+
28+ print_error () {
29+ echo -e " ${RED} [ERROR]${NC} $1 "
30+ }
31+
32+ print_success () {
33+ echo -e " ${GREEN} [SUCCESS]${NC} $1 "
34+ }
35+
36+ # Function to log messages
37+ log_message () {
38+ echo " $( date ' +%Y-%m-%d %H:%M:%S' ) - $1 " >> " ${LOG_FILE} "
39+ }
40+
41+ # Function to run dependency audit with pip-audit
42+ run_pip_audit () {
43+ print_status " Running pip-audit vulnerability scan..."
44+ log_message " Starting pip-audit scan"
45+
46+ if docker compose exec python pip-audit --format=json --output=" ${LOG_FILE} .pip-audit.json" 2> /dev/null; then
47+ print_success " pip-audit scan completed successfully"
48+ log_message " pip-audit scan completed successfully"
49+
50+ # Check if vulnerabilities were found
51+ if [ -f " ${LOG_FILE} .pip-audit.json" ]; then
52+ vuln_count=$( docker compose exec python jq ' .[] | length' " ${LOG_FILE} .pip-audit.json" 2> /dev/null || echo " 0" )
53+ if [ " ${vuln_count} " -gt 0 ]; then
54+ print_warning " Found ${vuln_count} vulnerabilities"
55+ log_message " Found ${vuln_count} vulnerabilities with pip-audit"
56+ return 1
57+ else
58+ print_success " No vulnerabilities found with pip-audit"
59+ fi
60+ fi
61+ else
62+ print_error " pip-audit scan failed"
63+ log_message " pip-audit scan failed"
64+ return 1
65+ fi
66+ }
67+
68+ # Function to run safety check
69+ run_safety_check () {
70+ print_status " Running Safety vulnerability scan..."
71+ log_message " Starting Safety scan"
72+
73+ if docker compose exec python safety check --json --output=" ${LOG_FILE} .safety.json" 2> /dev/null; then
74+ print_success " Safety scan completed successfully"
75+ log_message " Safety scan completed successfully"
76+
77+ # Check safety results
78+ if [ -f " ${LOG_FILE} .safety.json" ]; then
79+ safety_issues=$( docker compose exec python jq ' .vulnerabilities | length' " ${LOG_FILE} .safety.json" 2> /dev/null || echo " 0" )
80+ if [ " ${safety_issues} " -gt 0 ]; then
81+ print_warning " Found ${safety_issues} issues with Safety"
82+ log_message " Found ${safety_issues} issues with Safety"
83+ return 1
84+ else
85+ print_success " No issues found with Safety"
86+ fi
87+ fi
88+ else
89+ print_warning " Safety scan failed (may require API key for commercial use)"
90+ log_message " Safety scan failed"
91+ fi
92+ }
93+
94+ # Function to check for outdated packages
95+ check_outdated_packages () {
96+ print_status " Checking for outdated packages..."
97+ log_message " Checking for outdated packages"
98+
99+ if docker compose exec python pip list --outdated --format=json > " ${LOG_FILE} .outdated.json" 2> /dev/null; then
100+ outdated_count=$( jq ' . | length' " ${LOG_FILE} .outdated.json" 2> /dev/null || echo " 0" )
101+ if [ " ${outdated_count} " -gt 0 ]; then
102+ print_warning " Found ${outdated_count} outdated packages"
103+ log_message " Found ${outdated_count} outdated packages"
104+
105+ # Display top outdated packages
106+ print_status " Top outdated packages:"
107+ jq -r ' .[] | "\(.name): \(.version) -> \(.latest_version)"' " ${LOG_FILE} .outdated.json" | head -5
108+ else
109+ print_success " All packages are up to date"
110+ fi
111+ else
112+ print_error " Failed to check for outdated packages"
113+ log_message " Failed to check for outdated packages"
114+ return 1
115+ fi
116+ }
117+
118+ # Function to generate security report
119+ generate_security_report () {
120+ print_status " Generating security report..."
121+ log_message " Generating security report"
122+
123+ cat > " ${PROJECT_ROOT} /SECURITY_REPORT.md" << EOF
124+ # Dependency Security Report
125+
126+ Generated on: $( date ' +%Y-%m-%d %H:%M:%S' )
127+
128+ ## Summary
129+
130+ This report contains the results of automated dependency security scanning using pip-audit and Safety.
131+
132+ ## Scan Results
133+
134+ ### pip-audit Results
135+ $( if [ -f " ${LOG_FILE} .pip-audit.json" ]; then
136+ echo " Vulnerabilities found: $( jq ' .[] | length' " ${LOG_FILE} .pip-audit.json" 2> /dev/null || echo " 0" ) "
137+ else
138+ echo " No pip-audit results available"
139+ fi)
140+
141+ ### Safety Results
142+ $( if [ -f " ${LOG_FILE} .safety.json" ]; then
143+ echo " Issues found: $( jq ' .vulnerabilities | length' " ${LOG_FILE} .safety.json" 2> /dev/null || echo " 0" ) "
144+ else
145+ echo " No Safety results available"
146+ fi)
147+
148+ ### Outdated Packages
149+ $( if [ -f " ${LOG_FILE} .outdated.json" ]; then
150+ echo " Outdated packages: $( jq ' . | length' " ${LOG_FILE} .outdated.json" 2> /dev/null || echo " 0" ) "
151+ else
152+ echo " No outdated package information available"
153+ fi)
154+
155+ ## Recommendations
156+
157+ 1. Review and update outdated packages regularly
158+ 2. Monitor security advisories for dependencies
159+ 3. Use automated dependency update tools like Dependabot
160+ 4. Implement security scanning in CI/CD pipelines
161+ 5. Consider using dependency pinning for critical dependencies
162+
163+ ## Next Steps
164+
165+ - Update critical security vulnerabilities immediately
166+ - Plan regular dependency update cycles
167+ - Implement automated security monitoring
168+ - Review and update dependency management policies
169+
170+ EOF
171+
172+ print_success " Security report generated: ${PROJECT_ROOT} /SECURITY_REPORT.md"
173+ log_message " Security report generated"
174+ }
175+
176+ # Function to fix vulnerabilities automatically
177+ fix_vulnerabilities () {
178+ if [ " ${1:- } " = " --fix" ]; then
179+ print_status " Attempting to fix vulnerabilities automatically..."
180+ log_message " Starting automatic vulnerability fixes"
181+
182+ if docker compose exec python pip-audit --fix --dry-run; then
183+ print_status " Dry-run successful. Applying fixes..."
184+ if docker compose exec python pip-audit --fix; then
185+ print_success " Vulnerabilities fixed automatically"
186+ log_message " Vulnerabilities fixed automatically"
187+ else
188+ print_error " Failed to fix vulnerabilities automatically"
189+ log_message " Failed to fix vulnerabilities automatically"
190+ return 1
191+ fi
192+ else
193+ print_error " Dry-run failed. Manual intervention required"
194+ log_message " Automatic fix dry-run failed"
195+ return 1
196+ fi
197+ fi
198+ }
199+
200+ # Main execution
201+ main () {
202+ print_status " Starting dependency security audit..."
203+ log_message " Starting dependency security audit"
204+
205+ # Initialize log file
206+ echo " Dependency Security Audit Log" > " ${LOG_FILE} "
207+ echo " Started: $( date ' +%Y-%m-%d %H:%M:%S' ) " >> " ${LOG_FILE} "
208+
209+ # Change to project directory
210+ cd " ${PROJECT_ROOT} "
211+
212+ # Check if Docker containers are running
213+ if ! docker compose ps | grep -q " Up" ; then
214+ print_status " Starting Docker containers..."
215+ docker compose up -d python
216+ sleep 10
217+ fi
218+
219+ # Run security scans
220+ exit_code=0
221+
222+ run_pip_audit || exit_code=$?
223+ run_safety_check || exit_code=$?
224+ check_outdated_packages || exit_code=$?
225+
226+ # Generate report
227+ generate_security_report
228+
229+ # Attempt automatic fixes if requested
230+ fix_vulnerabilities " $@ "
231+
232+ # Summary
233+ if [ ${exit_code} -eq 0 ]; then
234+ print_success " All security scans passed!"
235+ log_message " All security scans passed"
236+ else
237+ print_warning " Security issues found. Please review the report."
238+ log_message " Security issues found"
239+ fi
240+
241+ print_status " Security audit completed. Check ${LOG_FILE} for details."
242+
243+ return ${exit_code}
244+ }
245+
246+ # Handle script arguments
247+ case " ${1:- } " in
248+ --help|-h)
249+ echo " Usage: $0 [--fix] [--help]"
250+ echo " --fix Attempt to automatically fix vulnerabilities"
251+ echo " --help Show this help message"
252+ exit 0
253+ ;;
254+ * )
255+ main " $@ "
256+ ;;
257+ esac
0 commit comments