Security Scanning¶
This document describes the security scanning tools and processes for the DSTA project.
Overview¶
DSTA uses two complementary security scanning tools:
- Bandit - Static code analysis to find common security issues in Python code
- Safety - Dependency vulnerability scanning to identify known security vulnerabilities in packages
Quick Start¶
Run All Security Scans Locally¶
This script will: - Install bandit and safety if not present - Run bandit code security scan - Run safety dependency vulnerability scan - Generate detailed reports in security-reports/
Run Individual Tools¶
Bandit (Code Security)¶
# Basic scan
bandit -r src/
# With configuration
bandit -r src/ -c .bandit
# Generate JSON report
bandit -r src/ -c .bandit -f json -o bandit-report.json
Safety (Dependency Vulnerabilities)¶
# Scan current environment
pip freeze > requirements.txt
safety check --file=requirements.txt
# With JSON output
safety check --file=requirements.txt --output=json --save-json=safety-report.json
Configuration¶
Bandit Configuration (.bandit)¶
Located at project root, controls: - Excluded directories (tests, venv, etc.) - Skipped test IDs - Confidence and severity thresholds - Output formatting
Example customizations:
# Skip specific test
skips = ['B101'] # Skip assert usage check
# Set thresholds
confidence = MEDIUM # LOW, MEDIUM, HIGH
severity = MEDIUM # LOW, MEDIUM, HIGH
Safety Configuration (.safety-policy.yml)¶
Located at project root, controls: - Ignored vulnerabilities (with expiration) - Ignored packages - Minimum severity threshold - Files to scan
Example customizations:
security:
ignore-vulnerabilities:
- id: "12345"
reason: "False positive - doesn't affect our usage"
expires: "2026-12-31"
minimum-severity: "high" # Only report high+ severity
CI/CD Integration¶
GitHub Actions Workflow¶
Security scans run automatically on: - Push to main or develop branches - Pull requests to main or develop - Daily at 2 AM UTC (scheduled)
Workflow file: .github/workflows/security.yml
Viewing Reports¶
- Go to Actions tab in GitHub
- Select "Security Scanning" workflow
- Click on latest run
- Download artifacts:
bandit-security-report- Bandit JSON resultssafety-vulnerability-report- Safety JSON results
Handling Failures¶
If security scan fails in CI:
- Check the workflow logs for details
- Download and review the artifact reports
- Fix identified issues or add exceptions (with justification)
- Re-run the workflow
Common Security Issues¶
Bandit Issues¶
B201/B301: Pickle Usage
# ❌ Insecure
import pickle
data = pickle.load(file)
# ✅ Secure - use JSON instead
import json
data = json.load(file)
B608: SQL Injection
# ❌ Insecure
query = f"SELECT * FROM users WHERE id = {user_id}"
# ✅ Secure - use parameterized queries
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
B105/B106: Hardcoded Passwords
# ❌ Insecure
password = "my_secret_password"
# ✅ Secure - use environment variables
import os
password = os.getenv("DB_PASSWORD")
B404: Import of subprocess
# If you need subprocess, use it safely:
import subprocess
# ✅ Avoid shell=True
subprocess.run(["ls", "-la"], check=True)
# ❌ Never use shell=True with user input
subprocess.run(f"ls {user_input}", shell=True) # DANGEROUS!
Safety Issues¶
When Safety finds vulnerabilities:
-
Update the package (preferred):
-
Check if vulnerability applies to your usage:
- Read the CVE details
-
Determine if your code uses the vulnerable feature
-
Add exception if needed (with strong justification):
Security Best Practices¶
Code Security¶
- Never hardcode secrets - use environment variables or secret management
- Validate all inputs - especially user-provided data
- Use parameterized queries - prevent SQL injection
- Avoid shell=True in subprocess calls
- Use safe deserialization - prefer JSON over pickle
- Keep dependencies updated - regularly run
pip list --outdated
API Security¶
- Use HTTPS for all external communications
- Validate API keys before use
- Rate limit API calls to prevent abuse
- Sanitize error messages - don't expose internal details
- Log security events - authentication, authorization failures
Django Security¶
- Use Django's built-in protection for CSRF, XSS, SQL injection
- Set DEBUG=False in production
- Configure ALLOWED_HOSTS properly
- Use strong SECRET_KEY from environment variable
- Enable security middleware
Ignoring False Positives¶
Bandit¶
To skip specific issues inline:
Or configure in .bandit:
Safety¶
Add to .safety-policy.yml:
security:
ignore-vulnerabilities:
- id: "CVE-2024-12345"
reason: "Detailed explanation..."
expires: "2026-12-31" # Must justify and set expiration
Maintenance¶
Weekly Tasks¶
- Review security reports from automated scans
- Update dependencies with security patches
- Review and remove expired exceptions
Monthly Tasks¶
- Run full security audit:
./scripts/security-scan.sh - Review all ignored vulnerabilities in
.safety-policy.yml - Update bandit and safety to latest versions
- Check for new security best practices
Before Each Release¶
- Run comprehensive security scan
- Ensure all known vulnerabilities are addressed
- Review and update security documentation
- Verify all secrets are properly externalized
Resources¶
- Bandit Documentation: https://bandit.readthedocs.io/
- Safety Documentation: https://docs.pyup.io/
- Python Security Best Practices: https://python.readthedocs.io/en/latest/library/security_warnings.html
- OWASP Top 10: https://owasp.org/www-project-top-ten/
- Django Security: https://docs.djangoproject.com/en/stable/topics/security/
Support¶
If you encounter security issues:
- Do not commit security vulnerabilities to the repository
- Run security scans before creating pull requests
- Document exceptions with clear justification and expiration dates
- Report critical security issues privately to the maintainers
For questions or issues with security scanning, open an issue with the security label.