$ -weight: 500;">pip -weight: 500;">install bandit
bandit -r my_project/
-weight: 500;">pip -weight: 500;">install bandit
bandit -r my_project/
-weight: 500;">pip -weight: 500;">install bandit
bandit -r my_project/
skips: ['B101', 'B601']
exclude_dirs: - tests/ - migrations/
skips: ['B101', 'B601']
exclude_dirs: - tests/ - migrations/
skips: ['B101', 'B601']
exclude_dirs: - tests/ - migrations/
# GitHub Actions example
- name: Security Check run: | -weight: 500;">pip -weight: 500;">install bandit bandit -r src/ -f json -o bandit-report.json if [ $? -ne 0 ]; then echo "::warning::Security issues found. Check bandit-report.json" fi
# GitHub Actions example
- name: Security Check run: | -weight: 500;">pip -weight: 500;">install bandit bandit -r src/ -f json -o bandit-report.json if [ $? -ne 0 ]; then echo "::warning::Security issues found. Check bandit-report.json" fi
# GitHub Actions example
- name: Security Check run: | -weight: 500;">pip -weight: 500;">install bandit bandit -r src/ -f json -o bandit-report.json if [ $? -ne 0 ]; then echo "::warning::Security issues found. Check bandit-report.json" fi
-weight: 500;">pip -weight: 500;">install safety
safety check --full-report
-weight: 500;">pip -weight: 500;">install safety
safety check --full-report
-weight: 500;">pip -weight: 500;">install safety
safety check --full-report
# safety_check.py
import subprocess
import json def check_dependencies(): result = subprocess.run( ["safety", "check", "--json"], capture_output=True, text=True ) if result.returncode != 0: vulnerabilities = json.loads(result.stdout) for vuln in vulnerabilities: print(f"[CRITICAL] {vuln['package']} {vuln['version']}") print(f" Vulnerability: {vuln['advisory']}") print(f" Fix: Upgrade to {vuln['fixed_version']}") return False return True
# safety_check.py
import subprocess
import json def check_dependencies(): result = subprocess.run( ["safety", "check", "--json"], capture_output=True, text=True ) if result.returncode != 0: vulnerabilities = json.loads(result.stdout) for vuln in vulnerabilities: print(f"[CRITICAL] {vuln['package']} {vuln['version']}") print(f" Vulnerability: {vuln['advisory']}") print(f" Fix: Upgrade to {vuln['fixed_version']}") return False return True
# safety_check.py
import subprocess
import json def check_dependencies(): result = subprocess.run( ["safety", "check", "--json"], capture_output=True, text=True ) if result.returncode != 0: vulnerabilities = json.loads(result.stdout) for vuln in vulnerabilities: print(f"[CRITICAL] {vuln['package']} {vuln['version']}") print(f" Vulnerability: {vuln['advisory']}") print(f" Fix: Upgrade to {vuln['fixed_version']}") return False return True
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64 # Symmetric encryption
key = Fernet.generate_key()
cipher = Fernet(key) encrypted = cipher.encrypt(b"sensitive data")
decrypted = cipher.decrypt(encrypted) # Secure password hashing
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os salt = os.urandom(16)
kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=480000,
)
key = kdf.derive(b"password")
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64 # Symmetric encryption
key = Fernet.generate_key()
cipher = Fernet(key) encrypted = cipher.encrypt(b"sensitive data")
decrypted = cipher.decrypt(encrypted) # Secure password hashing
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os salt = os.urandom(16)
kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=480000,
)
key = kdf.derive(b"password")
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64 # Symmetric encryption
key = Fernet.generate_key()
cipher = Fernet(key) encrypted = cipher.encrypt(b"sensitive data")
decrypted = cipher.decrypt(encrypted) # Secure password hashing
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os salt = os.urandom(16)
kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=480000,
)
key = kdf.derive(b"password")
-weight: 500;">pip -weight: 500;">install semgrep
semgrep --config=auto --security-severity=WARNING .
-weight: 500;">pip -weight: 500;">install semgrep
semgrep --config=auto --security-severity=WARNING .
-weight: 500;">pip -weight: 500;">install semgrep
semgrep --config=auto --security-severity=WARNING .
# Semgrep rule example
# rules/no-hardcoded-secrets.yml
rules: - id: detect-hardcoded-api-key patterns: - pattern-either: - pattern: $X = "$API_KEY" - pattern: $X = "$SECRET" - pattern: $X = "$TOKEN" message: "Possible hardcoded API key detected" severity: ERROR languages: [python]
# Semgrep rule example
# rules/no-hardcoded-secrets.yml
rules: - id: detect-hardcoded-api-key patterns: - pattern-either: - pattern: $X = "$API_KEY" - pattern: $X = "$SECRET" - pattern: $X = "$TOKEN" message: "Possible hardcoded API key detected" severity: ERROR languages: [python]
# Semgrep rule example
# rules/no-hardcoded-secrets.yml
rules: - id: detect-hardcoded-api-key patterns: - pattern-either: - pattern: $X = "$API_KEY" - pattern: $X = "$SECRET" - pattern: $X = "$TOKEN" message: "Possible hardcoded API key detected" severity: ERROR languages: [python]
# Install Trivy
-weight: 500;">curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/-weight: 500;">install.sh | sh -s -- -b /usr/local/bin # Scan a container image
trivy image my-python-app:latest # Scan a filesystem
trivy fs /path/to/project
# Install Trivy
-weight: 500;">curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/-weight: 500;">install.sh | sh -s -- -b /usr/local/bin # Scan a container image
trivy image my-python-app:latest # Scan a filesystem
trivy fs /path/to/project
# Install Trivy
-weight: 500;">curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/-weight: 500;">install.sh | sh -s -- -b /usr/local/bin # Scan a container image
trivy image my-python-app:latest # Scan a filesystem
trivy fs /path/to/project
# Multi-stage build with security scanning
FROM python:3.12-slim as builder
COPY requirements.txt .
RUN -weight: 500;">pip -weight: 500;">install --user -r requirements.txt FROM python:3.12-slim
COPY --from=builder /root/.local /root/.local
COPY . .
# Multi-stage build with security scanning
FROM python:3.12-slim as builder
COPY requirements.txt .
RUN -weight: 500;">pip -weight: 500;">install --user -r requirements.txt FROM python:3.12-slim
COPY --from=builder /root/.local /root/.local
COPY . .
# Multi-stage build with security scanning
FROM python:3.12-slim as builder
COPY requirements.txt .
RUN -weight: 500;">pip -weight: 500;">install --user -r requirements.txt FROM python:3.12-slim
COPY --from=builder /root/.local /root/.local
COPY . .
# Scan during build
trivy image --exit-code 1 --severity CRITICAL,HIGH my-python-app:latest
# Scan during build
trivy image --exit-code 1 --severity CRITICAL,HIGH my-python-app:latest
# Scan during build
trivy image --exit-code 1 --severity CRITICAL,HIGH my-python-app:latest - Hardcoded passwords and secrets: B105 and B106 rules catch hardcoded passwords and passwords in function defaults
- SQL injection: Detects string formatting in SQL queries
- Insecure YAML loading: Flags yaml.load() without a safe loader
- Shell injection: Catches unsafe use of subprocess and os.system
- Insecure temp files: Detects use of tempfile.mktemp instead of mkstemp - Scans against PyUp's vulnerability database with over 300,000 entries
- Supports requirements.txt, Pipfile, Pipfile.lock, and setup.py
- Can be integrated into CI/CD pipelines
- Provides detailed CVE information and remediation advice - Always use Fernet for symmetric encryption (it handles IVs and authentication)
- Use PBKDF2 with at least 480,000 iterations for password hashing
- Never roll your own crypto — use the library's high-level APIs
- Store salts alongside hashes but never reuse them - Tainted data flow: Track user input from HTTP endpoints to database queries
- Authentication bypass: Detect missing auth checks on protected endpoints
- Insecure deserialization: Flag pickle.loads() on untrusted data
- Path traversal: Catch unsanitized file path operations