Skip to content

Security Scanning

Security Scanning #199

Workflow file for this run

name: Security Scanning
on:
pull_request:
branches: [ main, develop ]
push:
branches: [ main, develop ]
schedule:
# Run weekly on Mondays at 9:00 AM UTC
- cron: '0 9 * * 1'
workflow_dispatch:
permissions:
contents: read
security-events: write
jobs:
secret-scan:
name: Secret Scanning
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # Full history for better secret detection
- name: TruffleHog Secret Scan
uses: trufflesecurity/trufflehog@main
with:
extra_args: --only-verified
- name: Gitleaks Secret Scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check for common secret patterns
run: |
echo "Checking for common secret patterns..."
# Check for AWS keys
if git grep -iE 'AKIA[0-9A-Z]{16}' -- ':!.github/workflows/security.yml'; then
echo "⚠ Warning: Found potential AWS access key"
fi
# Check for private keys
if git grep -l 'BEGIN.*PRIVATE KEY' -- ':!.github/workflows/security.yml'; then
echo "⚠ Warning: Found potential private key"
fi
# Check for generic secrets
if git grep -iE '(password|passwd|pwd|secret|token|api_key|apikey).*=.*["\047][^"\047]{20,}["\047]' -- ':!.github/workflows/security.yml' ':!*.md'; then
echo "⚠ Warning: Found potential hardcoded secrets"
fi
echo "✓ Secret pattern check completed"
dependency-scan:
name: Dependency Scanning
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check for Python dependencies
id: check-python
run: |
if [ -f "requirements.txt" ] || find . -name "requirements.txt" -type f | grep -q .; then
echo "has_python=true" >> $GITHUB_OUTPUT
else
echo "has_python=false" >> $GITHUB_OUTPUT
fi
- name: Set up Python
if: steps.check-python.outputs.has_python == 'true'
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install Safety
if: steps.check-python.outputs.has_python == 'true'
run: pip install safety
- name: Check Python dependencies
if: steps.check-python.outputs.has_python == 'true'
run: |
find . -name "requirements.txt" -type f | while read req_file; do
echo "Checking $req_file..."
safety check --file "$req_file" --output text || true
done
continue-on-error: true
- name: Check Docker image vulnerabilities
run: |
echo "Extracting Docker images from docker-compose.yml..."
# Get unique images from docker-compose.yml
images=$(grep -E "^\s+image:" docker-compose.yml | awk '{print $2}' | sort -u)
echo "Found images:"
echo "$images"
echo ""
echo "Note: For full vulnerability scanning, consider using:"
echo " - Trivy: trivy image <image>"
echo " - Snyk: snyk container test <image>"
echo " - Docker Scout: docker scout cves <image>"
trivy-scan:
name: Trivy Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: 'trivy-results.sarif'
- name: Run Trivy for configuration files
uses: aquasecurity/trivy-action@master
with:
scan-type: 'config'
scan-ref: '.'
format: 'table'
exit-code: '0'
severity: 'CRITICAL,HIGH,MEDIUM'
docker-compose-security:
name: Docker Compose Security Review
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check for security best practices
run: |
echo "Checking Docker Compose security configuration..."
issues=0
# Check for privileged containers
if grep -q "privileged: true" docker-compose.yml; then
echo "⚠ Warning: Found privileged containers - security risk"
issues=$((issues + 1))
fi
# Check for host network mode
if grep -q "network_mode:.*host" docker-compose.yml; then
echo "⚠ Warning: Found host network mode - potential security risk"
issues=$((issues + 1))
fi
# Check for volume mounts to root
if grep -q "/:/.*:rw" docker-compose.yml; then
echo "⚠ Warning: Found read-write mount to host root - security risk"
issues=$((issues + 1))
fi
# Check for missing read-only root filesystem
if ! grep -q "read_only: true" docker-compose.yml; then
echo "ℹ Info: Consider using read-only root filesystems where possible"
fi
# Check for missing resource limits
if ! grep -q "limits:" docker-compose.yml; then
echo "ℹ Info: Consider adding resource limits to prevent DoS"
fi
# Check for exposed ports
if grep -q "0.0.0.0:" docker-compose.yml; then
echo "ℹ Info: Services exposed on 0.0.0.0 - ensure this is intended"
fi
if [ $issues -eq 0 ]; then
echo "✓ No critical security issues found in Docker Compose"
else
echo ""
echo "Found $issues security warning(s) in Docker Compose configuration"
fi
env-security:
name: Environment File Security
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check .env.example for weak defaults
run: |
echo "Checking .env.example for security issues..."
issues=0
# Check for weak passwords
weak_patterns=(
"password=password"
"password=admin"
"password=12345"
"password=test"
)
for pattern in "${weak_patterns[@]}"; do
if grep -iq "$pattern" .env.example; then
echo "⚠ Warning: Found weak default password pattern"
issues=$((issues + 1))
break
fi
done
# Check for empty password fields
if grep -E "PASSWORD=\s*$" .env.example; then
echo "⚠ Warning: Found empty password fields"
issues=$((issues + 1))
fi
# Verify security-related settings
if ! grep -q "VAULT_" .env.example; then
echo "ℹ Info: No Vault configuration found"
fi
if [ $issues -eq 0 ]; then
echo "✓ No critical security issues found in .env.example"
else
echo ""
echo "Found $issues security issue(s) in .env.example"
fi
- name: Ensure .env is gitignored
run: |
if [ -f .gitignore ]; then
if grep -q "^\.env$" .gitignore; then
echo "✓ .env is properly gitignored"
else
echo "⚠ Warning: .env should be added to .gitignore"
exit 1
fi
else
echo "⚠ Warning: No .gitignore file found"
exit 1
fi
script-security:
name: Shell Script Security
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check for common shell script vulnerabilities
run: |
echo "Checking shell scripts for security issues..."
scripts=$(find . -name "*.sh" -type f)
for script in $scripts; do
echo "Checking $script..."
# Check for unquoted variables
if grep -E '\$[A-Za-z_][A-Za-z0-9_]*[^"\x27]' "$script" | grep -v "^\s*#"; then
echo " ℹ Info: Consider quoting variables to prevent word splitting"
fi
# Check for use of eval
if grep -q "eval " "$script"; then
echo " ⚠ Warning: Found 'eval' - potential code injection risk"
fi
# Check for curl/wget without verification
if grep -E "(curl|wget).*-k|--insecure" "$script"; then
echo " ⚠ Warning: Found insecure curl/wget usage"
fi
# Check for use of /tmp without mktemp
if grep -q "/tmp/[a-zA-Z]" "$script"; then
echo " ℹ Info: Consider using mktemp for temporary files"
fi
done
echo "✓ Script security check completed"
codeql-analysis-python:
name: CodeQL Analysis (Python)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install dependencies for CodeQL analysis
run: |
# Install dependencies from all requirements.txt files
# This helps CodeQL understand imports and dependencies
echo "Installing dependencies from reference apps..."
if [ -f "reference-apps/fastapi/requirements.txt" ]; then
pip install -r reference-apps/fastapi/requirements.txt || true
fi
if [ -f "reference-apps/fastapi-api-first/requirements.txt" ]; then
pip install -r reference-apps/fastapi-api-first/requirements.txt || true
fi
if [ -f "tests/requirements.txt" ]; then
pip install -r tests/requirements.txt || true
fi
if [ -f "reference-apps/shared/test-suite/requirements.txt" ]; then
pip install -r reference-apps/shared/test-suite/requirements.txt || true
fi
echo "✓ Dependencies installed for CodeQL analysis"
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: 'python'
queries: security-and-quality
setup-python-dependencies: false
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:python"
codeql-analysis-go:
name: CodeQL Analysis (Go)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'reference-apps/golang/go.mod'
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: 'go'
queries: security-and-quality
- name: Build Go application
run: |
echo "Building Go application for CodeQL analysis..."
cd reference-apps/golang
go build -v ./...
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:go"
security-summary:
name: Security Summary
runs-on: ubuntu-latest
needs:
- secret-scan
- dependency-scan
- trivy-scan
- docker-compose-security
- env-security
- script-security
- codeql-analysis-python
- codeql-analysis-go
if: always()
steps:
- name: Check security scan results
run: |
failed=0
if [ "${{ needs.secret-scan.result }}" == "failure" ]; then
echo "❌ Secret scanning failed - potential secrets detected"
failed=1
fi
if [ "${{ needs.env-security.result }}" == "failure" ]; then
echo "❌ Environment security check failed"
failed=1
fi
if [ "${{ needs.trivy-scan.result }}" == "failure" ]; then
echo "⚠ Warning: Trivy scan found vulnerabilities"
fi
if [ $failed -eq 1 ]; then
echo ""
echo "Critical security issues detected. Please review and fix before merging."
exit 1
fi
echo "✅ Security scans completed"
echo ""
echo "Please review any warnings in the individual job outputs."