🔒 Security Scanning #74
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🔒 Security Scanning | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| schedule: | |
| # Run security scans daily at 2 AM UTC | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| scan_type: | |
| description: 'Type of security scan' | |
| required: true | |
| default: 'full' | |
| type: choice | |
| options: | |
| - full | |
| - dependencies | |
| - code | |
| - secrets | |
| - docker | |
| env: | |
| DOTNET_VERSION: '9.0.x' | |
| NODE_VERSION: '18' | |
| # Concurrency: cancel previous runs on new push | |
| concurrency: | |
| group: security-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ============================================================================= | |
| # Dependency Vulnerability Scanning | |
| # ============================================================================= | |
| dependency-scan: | |
| name: 🔍 Dependency Scan | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.inputs.scan_type == 'full' || | |
| github.event.inputs.scan_type == 'dependencies' || | |
| github.event_name != 'workflow_dispatch' | |
| timeout-minutes: 15 | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| - name: ⚡ Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: 📦 Restore dependencies | |
| run: | | |
| cd backend | |
| dotnet restore | |
| - name: 🔍 .NET dependency vulnerability scan | |
| run: | | |
| echo "🔍 Scanning .NET dependencies for vulnerabilities..." | |
| cd backend | |
| # List all packages with vulnerabilities | |
| dotnet list package --vulnerable --include-transitive 2>&1 | tee dependency-scan.log | |
| # Check if any vulnerabilities were found | |
| if grep -i "vulnerable" dependency-scan.log; then | |
| echo "⚠️ Vulnerable dependencies detected!" | |
| # Extract vulnerability details | |
| echo "📋 Vulnerability Summary:" >> security-summary.md | |
| echo "## 🔍 Dependency Vulnerabilities" >> security-summary.md | |
| echo '```' >> security-summary.md | |
| grep -A 10 -B 2 "vulnerable" dependency-scan.log >> security-summary.md | |
| echo '```' >> security-summary.md | |
| # Set severity based on vulnerability type | |
| if grep -i "critical\|high" dependency-scan.log; then | |
| echo "SEVERITY=high" >> $GITHUB_ENV | |
| exit 1 # Fail on high/critical vulnerabilities | |
| else | |
| echo "SEVERITY=medium" >> $GITHUB_ENV | |
| fi | |
| else | |
| echo "✅ No vulnerable dependencies found" | |
| echo "SEVERITY=none" >> $GITHUB_ENV | |
| fi | |
| - name: ⚡ Setup Node.js | |
| if: always() | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| cache-dependency-path: 'frontend/package.json' | |
| - name: 🔍 NPM audit | |
| if: always() | |
| run: | | |
| echo "🔍 Scanning npm dependencies..." | |
| cd frontend | |
| # Install dependencies first (using npm for compatibility with audit) | |
| npm install | |
| # Run npm audit | |
| npm audit --audit-level=moderate --json > npm-audit.json 2>/dev/null || true | |
| # Check results | |
| if [[ -s npm-audit.json ]]; then | |
| VULNERABILITY_COUNT=$(cat npm-audit.json | jq '.metadata.vulnerabilities.total' 2>/dev/null || echo "0") | |
| if [[ "$VULNERABILITY_COUNT" -gt 0 ]]; then | |
| echo "⚠️ Found $VULNERABILITY_COUNT npm vulnerabilities" | |
| echo "## 📦 NPM Vulnerabilities" >> security-summary.md | |
| echo "**Total vulnerabilities:** $VULNERABILITY_COUNT" >> security-summary.md | |
| echo '```json' >> security-summary.md | |
| cat npm-audit.json | jq '.vulnerabilities' | head -50 >> security-summary.md | |
| echo '```' >> security-summary.md | |
| else | |
| echo "✅ No npm vulnerabilities found" | |
| fi | |
| fi | |
| - name: 📊 Upload dependency scan results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dependency-scan-results | |
| path: | | |
| dependency-scan.log | |
| npm-audit.json | |
| security-summary.md | |
| retention-days: 30 | |
| # ============================================================================= | |
| # Code Security Analysis | |
| # ============================================================================= | |
| code-security: | |
| name: 🔍 Code Security Analysis | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.inputs.scan_type == 'full' || | |
| github.event.inputs.scan_type == 'code' || | |
| github.event_name != 'workflow_dispatch' | |
| timeout-minutes: 20 | |
| permissions: | |
| security-events: write | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Full history for better analysis | |
| - name: 🔍 Initialize CodeQL | |
| uses: github/codeql-action/init@v3 | |
| with: | |
| languages: csharp | |
| queries: +security-extended,security-and-quality | |
| - name: ⚡ Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ env.DOTNET_VERSION }} | |
| - name: 🏗️ Build for CodeQL analysis | |
| run: | | |
| cd backend | |
| dotnet restore | |
| dotnet build --no-restore --configuration Release | |
| - name: 🔍 Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v3 | |
| with: | |
| category: '/language:csharp' | |
| - name: 🔍 Semgrep security scan | |
| uses: semgrep/semgrep-action@v1 | |
| with: | |
| config: >- | |
| p/security-audit | |
| p/secrets | |
| p/owasp-top-ten | |
| p/cwe-top-25 | |
| p/r2c-best-practices | |
| publishToken: ${{ secrets.SEMGREP_APP_TOKEN }} | |
| publishDeployment: ${{ github.event_name == 'push' }} | |
| generateSarif: true | |
| - name: 📊 Upload Semgrep SARIF | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: semgrep.sarif | |
| # ============================================================================= | |
| # Secret Scanning | |
| # ============================================================================= | |
| secret-scan: | |
| name: 🔐 Secret Scanning | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.inputs.scan_type == 'full' || | |
| github.event.inputs.scan_type == 'secrets' || | |
| github.event_name != 'workflow_dispatch' | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: 🔐 TruffleHog secret scan | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: . | |
| extra_args: --debug --only-verified | |
| - name: 🔐 GitLeaks secret scan | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} | |
| - name: 🔍 Manual secret pattern check | |
| run: | | |
| echo "🔍 Checking for common secret patterns..." | |
| # Create patterns file | |
| cat > secret-patterns.txt << 'EOF' | |
| password\s*=\s*['""][^'""]{8,}['""] | |
| api[_-]?key\s*[=:]\s*['""][^'""]+['""] | |
| secret[_-]?key\s*[=:]\s*['""][^'""]+['""] | |
| private[_-]?key\s*[=:]\s*['""][^'""]+['""] | |
| token\s*[=:]\s*['""][^'""]+['""] | |
| connectionstring\s*[=:]\s*['""][^'""]+['""] | |
| aws[_-]?access[_-]?key | |
| aws[_-]?secret[_-]?key | |
| github[_-]?token | |
| EOF | |
| # Search for patterns (excluding test files and this workflow) | |
| FOUND_SECRETS=false | |
| while IFS= read -r pattern; do | |
| if grep -r -i -n --exclude-dir=.git --exclude="*.yml" --exclude="*test*" "$pattern" . 2>/dev/null; then | |
| FOUND_SECRETS=true | |
| echo "⚠️ Potential secret found: $pattern" | |
| fi | |
| done < secret-patterns.txt | |
| if [[ "$FOUND_SECRETS" == "true" ]]; then | |
| echo "❌ Potential secrets detected in code" | |
| exit 1 | |
| else | |
| echo "✅ No obvious secret patterns found" | |
| fi | |
| # ============================================================================= | |
| # Docker Security Scanning | |
| # ============================================================================= | |
| docker-security: | |
| name: 🐳 Docker Security | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.inputs.scan_type == 'full' || | |
| github.event.inputs.scan_type == 'docker' || | |
| github.event_name != 'workflow_dispatch' | |
| timeout-minutes: 15 | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| - name: 🐳 Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: 🏗️ Build backend Docker image for scanning | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./backend | |
| file: ./backend/Dockerfile | |
| tags: modernapi-backend:security-scan | |
| load: true | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: 🏗️ Build frontend Docker image for scanning | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./frontend | |
| file: ./frontend/Dockerfile | |
| tags: modernapi-frontend:security-scan | |
| load: true | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: 🔍 Run Trivy backend container scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'modernapi-backend:security-scan' | |
| format: 'sarif' | |
| output: 'trivy-backend-results.sarif' | |
| - name: 🔍 Run Trivy frontend container scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'modernapi-frontend:security-scan' | |
| format: 'sarif' | |
| output: 'trivy-frontend-results.sarif' | |
| - name: 📊 Upload Trivy backend scan results | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: 'trivy-backend-results.sarif' | |
| - name: 📊 Upload Trivy frontend scan results | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: 'trivy-frontend-results.sarif' | |
| - name: 🔍 Run Trivy filesystem scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-fs-results.sarif' | |
| - name: 📊 Upload Trivy filesystem scan results | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: 'trivy-fs-results.sarif' | |
| - name: 🔍 Dockerfile best practices check | |
| run: | | |
| echo "🔍 Checking Dockerfile best practices..." | |
| # Install hadolint | |
| wget -O hadolint https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64 | |
| chmod +x hadolint | |
| # Run hadolint on backend Dockerfile | |
| ./hadolint backend/Dockerfile --format json > dockerfile-backend-scan.json || true | |
| # Run hadolint on frontend Dockerfile | |
| ./hadolint frontend/Dockerfile --format json > dockerfile-frontend-scan.json || true | |
| # Combine results | |
| echo "[]" > dockerfile-scan.json | |
| # Check backend results | |
| if [[ -s dockerfile-backend-scan.json ]]; then | |
| BACKEND_ERROR_COUNT=$(cat dockerfile-backend-scan.json | jq 'length' 2>/dev/null || echo "0") | |
| if [[ "$BACKEND_ERROR_COUNT" -gt 0 ]]; then | |
| echo "⚠️ Found $BACKEND_ERROR_COUNT backend Dockerfile issues" | |
| echo "## 🐳 Backend Dockerfile Issues" >> docker-security-summary.md | |
| echo '```json' >> docker-security-summary.md | |
| cat dockerfile-backend-scan.json >> docker-security-summary.md | |
| echo '```' >> docker-security-summary.md | |
| # Add to combined results | |
| jq -s '.[0] + .[1]' dockerfile-scan.json dockerfile-backend-scan.json > temp.json && mv temp.json dockerfile-scan.json | |
| fi | |
| fi | |
| # Check frontend results | |
| if [[ -s dockerfile-frontend-scan.json ]]; then | |
| FRONTEND_ERROR_COUNT=$(cat dockerfile-frontend-scan.json | jq 'length' 2>/dev/null || echo "0") | |
| if [[ "$FRONTEND_ERROR_COUNT" -gt 0 ]]; then | |
| echo "⚠️ Found $FRONTEND_ERROR_COUNT frontend Dockerfile issues" | |
| echo "## 🐳 Frontend Dockerfile Issues" >> docker-security-summary.md | |
| echo '```json' >> docker-security-summary.md | |
| cat dockerfile-frontend-scan.json >> docker-security-summary.md | |
| echo '```' >> docker-security-summary.md | |
| # Add to combined results | |
| jq -s '.[0] + .[1]' dockerfile-scan.json dockerfile-frontend-scan.json > temp.json && mv temp.json dockerfile-scan.json | |
| fi | |
| fi | |
| - name: 🔍 Docker Scout backend vulnerability scan | |
| if: github.event_name != 'pull_request' | |
| uses: docker/scout-action@v1 | |
| with: | |
| command: cves | |
| image: modernapi-backend:security-scan | |
| sarif-file: scout-backend-results.sarif | |
| - name: 🔍 Docker Scout frontend vulnerability scan | |
| if: github.event_name != 'pull_request' | |
| uses: docker/scout-action@v1 | |
| with: | |
| command: cves | |
| image: modernapi-frontend:security-scan | |
| sarif-file: scout-frontend-results.sarif | |
| - name: 📊 Upload Docker Scout backend results | |
| if: always() && github.event_name != 'pull_request' | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: scout-backend-results.sarif | |
| - name: 📊 Upload Docker Scout frontend results | |
| if: always() && github.event_name != 'pull_request' | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: scout-frontend-results.sarif | |
| - name: 📊 Upload Docker security scan results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: docker-security-results | |
| path: | | |
| trivy-backend-results.sarif | |
| trivy-frontend-results.sarif | |
| trivy-fs-results.sarif | |
| dockerfile-scan.json | |
| dockerfile-backend-scan.json | |
| dockerfile-frontend-scan.json | |
| docker-security-summary.md | |
| scout-backend-results.sarif | |
| scout-frontend-results.sarif | |
| retention-days: 30 | |
| # ============================================================================= | |
| # Infrastructure Security | |
| # ============================================================================= | |
| infrastructure-security: | |
| name: 🏗️ Infrastructure Security | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event.inputs.scan_type == 'full' || | |
| github.event_name == 'schedule' || | |
| github.event_name == 'push' | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| - name: 🔍 Kubernetes security scan | |
| if: hashFiles('k8s/**/*.yml') != '' | |
| run: | | |
| echo "🔍 Scanning Kubernetes manifests..." | |
| # Install kube-score | |
| wget -O kube-score https://github.com/zegl/kube-score/releases/latest/download/kube-score_linux_amd64 | |
| chmod +x kube-score | |
| # Scan Kubernetes manifests | |
| if [[ -d "k8s" ]]; then | |
| ./kube-score score k8s/*.yml --output-format json > k8s-security-scan.json 2>/dev/null || true | |
| if [[ -s k8s-security-scan.json ]]; then | |
| echo "📊 Kubernetes security analysis completed" | |
| cat k8s-security-scan.json | jq '.[] | select(.grade < 7)' > k8s-issues.json | |
| if [[ -s k8s-issues.json ]]; then | |
| echo "⚠️ Kubernetes security issues found" | |
| echo "## ☸️ Kubernetes Security Issues" >> infra-security-summary.md | |
| echo '```json' >> infra-security-summary.md | |
| cat k8s-issues.json >> infra-security-summary.md | |
| echo '```' >> infra-security-summary.md | |
| fi | |
| fi | |
| fi | |
| - name: 🔍 Docker Compose security check | |
| if: hashFiles('docker-compose*.yml') != '' | |
| run: | | |
| echo "🔍 Checking Docker Compose security..." | |
| # Check for common security issues in docker-compose files | |
| find . -name "docker-compose*.yml" | while read -r file; do | |
| echo "Checking $file..." | |
| # Check for privileged containers | |
| if grep -q "privileged.*true" "$file"; then | |
| echo "⚠️ Privileged container found in $file" | |
| fi | |
| # Check for host network mode | |
| if grep -q "network_mode.*host" "$file"; then | |
| echo "⚠️ Host network mode found in $file" | |
| fi | |
| # Check for volume mounts to sensitive directories | |
| if grep -q "/var/run/docker.sock" "$file"; then | |
| echo "⚠️ Docker socket mount found in $file" | |
| fi | |
| # Check for default passwords | |
| if grep -i -E "(password|secret).*=.*(password|secret|admin|root)" "$file"; then | |
| echo "⚠️ Potential default password found in $file" | |
| fi | |
| done | |
| - name: 🔍 GitHub Actions security check | |
| run: | | |
| echo "🔍 Checking GitHub Actions security..." | |
| # Check workflow files for security issues | |
| find .github/workflows -name "*.yml" | while read -r workflow; do | |
| echo "Checking workflow: $workflow" | |
| # Check for dangerous permissions | |
| if grep -q "permissions:.*write-all" "$workflow"; then | |
| echo "⚠️ Overly broad permissions in $workflow" | |
| fi | |
| # Check for hardcoded secrets | |
| if grep -i -E "(api[_-]?key|secret|token|password).*[=:].*(sk-|ghp_|gho_)" "$workflow"; then | |
| echo "⚠️ Potential hardcoded secret in $workflow" | |
| fi | |
| # Check for external action versions | |
| grep -E "uses:.*@(?!v[0-9])" "$workflow" | while read -r line; do | |
| echo "ℹ️ Unversioned action found: $line" | |
| done | |
| done | |
| - name: 📊 Upload infrastructure security results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: infrastructure-security-results | |
| path: | | |
| k8s-security-scan.json | |
| k8s-issues.json | |
| infra-security-summary.md | |
| retention-days: 30 | |
| # ============================================================================= | |
| # Security Summary & Reporting | |
| # ============================================================================= | |
| security-summary: | |
| name: 📊 Security Summary | |
| runs-on: ubuntu-latest | |
| needs: [dependency-scan, code-security, secret-scan, docker-security, infrastructure-security] | |
| if: always() | |
| steps: | |
| - name: 📥 Download all security artifacts | |
| if: always() | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: security-results | |
| - name: 📊 Generate security summary | |
| if: always() | |
| run: | | |
| echo "📊 Generating comprehensive security summary..." | |
| cat > security-report.md << 'EOF' | |
| # 🔒 Security Scan Report | |
| **Scan Date:** $(date -u) | |
| **Repository:** ${{ github.repository }} | |
| **Branch:** ${{ github.ref_name }} | |
| **Commit:** ${{ github.sha }} | |
| ## 📋 Scan Results Overview | |
| | Component | Status | Issues | | |
| |-----------|--------|---------| | |
| EOF | |
| # Dependency scan results | |
| if [[ -f "security-results/dependency-scan-results/dependency-scan.log" ]]; then | |
| if grep -q "vulnerable" security-results/dependency-scan-results/dependency-scan.log; then | |
| echo "| Dependencies | ❌ Issues Found | [Details](#dependencies) |" >> security-report.md | |
| else | |
| echo "| Dependencies | ✅ Clean | None |" >> security-report.md | |
| fi | |
| else | |
| echo "| Dependencies | ⏭️ Skipped | N/A |" >> security-report.md | |
| fi | |
| # Code security results | |
| if [[ -d "security-results/code-security-results" ]]; then | |
| echo "| Code Analysis | ✅ Completed | [Details](#code-analysis) |" >> security-report.md | |
| else | |
| echo "| Code Analysis | ⏭️ Skipped | N/A |" >> security-report.md | |
| fi | |
| # Secret scan results | |
| NEEDS_SECRET_CHECK="${{ needs.secret-scan.result }}" | |
| if [[ "$NEEDS_SECRET_CHECK" == "success" ]]; then | |
| echo "| Secret Scan | ✅ Clean | None |" >> security-report.md | |
| elif [[ "$NEEDS_SECRET_CHECK" == "failure" ]]; then | |
| echo "| Secret Scan | ❌ Issues Found | [Details](#secrets) |" >> security-report.md | |
| else | |
| echo "| Secret Scan | ⏭️ Skipped | N/A |" >> security-report.md | |
| fi | |
| # Docker security results | |
| if [[ -d "security-results/docker-security-results" ]]; then | |
| echo "| Docker Security | ✅ Completed | [Details](#docker) |" >> security-report.md | |
| else | |
| echo "| Docker Security | ⏭️ Skipped | N/A |" >> security-report.md | |
| fi | |
| # Infrastructure security results | |
| if [[ -d "security-results/infrastructure-security-results" ]]; then | |
| echo "| Infrastructure | ✅ Completed | [Details](#infrastructure) |" >> security-report.md | |
| else | |
| echo "| Infrastructure | ⏭️ Skipped | N/A |" >> security-report.md | |
| fi | |
| # Add detailed sections | |
| echo "" >> security-report.md | |
| echo "## 📖 Detailed Results" >> security-report.md | |
| # Include dependency details if available | |
| if [[ -f "security-results/dependency-scan-results/security-summary.md" ]]; then | |
| echo "" >> security-report.md | |
| echo "### Dependencies" >> security-report.md | |
| cat security-results/dependency-scan-results/security-summary.md >> security-report.md | |
| fi | |
| # Include Docker details if available | |
| if [[ -f "security-results/docker-security-results/docker-security-summary.md" ]]; then | |
| echo "" >> security-report.md | |
| echo "### Docker" >> security-report.md | |
| cat security-results/docker-security-results/docker-security-summary.md >> security-report.md | |
| fi | |
| # Include infrastructure details if available | |
| if [[ -f "security-results/infrastructure-security-results/infra-security-summary.md" ]]; then | |
| echo "" >> security-report.md | |
| echo "### Infrastructure" >> security-report.md | |
| cat security-results/infrastructure-security-results/infra-security-summary.md >> security-report.md | |
| fi | |
| # Add recommendations | |
| echo "" >> security-report.md | |
| echo "## 🚀 Recommendations" >> security-report.md | |
| echo "1. Review and address any high/critical vulnerabilities immediately" >> security-report.md | |
| echo "2. Update dependencies to latest secure versions" >> security-report.md | |
| echo "3. Implement security headers and best practices" >> security-report.md | |
| echo "4. Regular security scans in CI/CD pipeline" >> security-report.md | |
| echo "5. Security awareness training for development team" >> security-report.md | |
| echo "✅ Security report generated" | |
| - name: 📊 Create security summary for GitHub | |
| if: always() | |
| run: | | |
| echo "## 🔒 Security Scan Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "**Scan completed at:** $(date -u)" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Overall status | |
| OVERALL_STATUS="✅ Passed" | |
| if [[ "${{ needs.dependency-scan.result }}" == "failure" || | |
| "${{ needs.secret-scan.result }}" == "failure" ]]; then | |
| OVERALL_STATUS="❌ Issues Found" | |
| fi | |
| echo "**Overall Status:** $OVERALL_STATUS" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📋 Scan Results" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Dependencies:** ${{ needs.dependency-scan.result || 'skipped' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Code Security:** ${{ needs.code-security.result || 'skipped' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Secret Scan:** ${{ needs.secret-scan.result || 'skipped' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Docker Security:** ${{ needs.docker-security.result || 'skipped' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Infrastructure:** ${{ needs.infrastructure-security.result || 'skipped' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ "$OVERALL_STATUS" == "❌ Issues Found" ]]; then | |
| echo "⚠️ **Action Required:** Please review and address security issues before deployment." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "🎉 **All security scans passed!** Ready for deployment." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: 📊 Upload comprehensive security report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: comprehensive-security-report | |
| path: | | |
| security-report.md | |
| security-results/ | |
| retention-days: 90 | |
| # Optional: Create GitHub issue for security findings | |
| - name: 🚨 Create security issue | |
| if: | | |
| always() && | |
| (needs.dependency-scan.result == 'failure' || needs.secret-scan.result == 'failure') && | |
| github.event_name == 'schedule' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const title = `🔒 Security Issues Detected - ${new Date().toISOString().split('T')[0]}`; | |
| const body = ` | |
| # 🔒 Automated Security Scan Results | |
| **Scan Date:** ${new Date().toISOString()} | |
| **Repository:** ${{ github.repository }} | |
| **Branch:** ${{ github.ref_name }} | |
| ## ⚠️ Issues Detected | |
| The automated security scan has detected potential security issues that require attention: | |
| - **Dependencies:** ${{ needs.dependency-scan.result }} | |
| - **Secret Scan:** ${{ needs.secret-scan.result }} | |
| - **Code Security:** ${{ needs.code-security.result }} | |
| ## 🔗 Detailed Reports | |
| Download the comprehensive security report from the [workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}). | |
| ## 🚀 Action Items | |
| 1. Review all high and critical severity findings | |
| 2. Update vulnerable dependencies | |
| 3. Address any secrets found in code | |
| 4. Implement recommended security fixes | |
| 5. Re-run security scans to verify fixes | |
| ## 📋 Checklist | |
| - [ ] Review dependency vulnerabilities | |
| - [ ] Address secret scanning findings | |
| - [ ] Update vulnerable packages | |
| - [ ] Test security fixes | |
| - [ ] Re-run security scans | |
| - [ ] Close this issue when all critical issues are resolved | |
| --- | |
| *This issue was automatically created by the security scanning workflow.* | |
| `; | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['security', 'bug', 'priority-high'] | |
| }); |