Security Scanning #41
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 ] | |
| pull_request: | |
| branches: [ main ] | |
| schedule: | |
| - cron: '0 2 * * *' # Daily at 2 AM | |
| jobs: | |
| codeql: | |
| name: CodeQL Analysis | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: read | |
| contents: read | |
| security-events: write | |
| strategy: | |
| matrix: | |
| language: [ 'python', 'javascript' ] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v2 | |
| with: | |
| languages: ${{ matrix.language }} | |
| - name: Autobuild | |
| uses: github/codeql-action/autobuild@v2 | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v2 | |
| dependency-scan: | |
| name: Dependency Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Run Snyk to check Python dependencies | |
| uses: snyk/actions/python@master | |
| continue-on-error: true | |
| env: | |
| SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} | |
| with: | |
| args: --severity-threshold=high | |
| - name: Run Snyk to check JavaScript dependencies | |
| uses: snyk/actions/node@master | |
| continue-on-error: true | |
| env: | |
| SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} | |
| with: | |
| args: --severity-threshold=high --file=frontend/package.json | |
| container-scan: | |
| name: Container Security Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build backend image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./backend | |
| load: true | |
| tags: valtronics/backend:test | |
| - name: Build frontend image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./frontend | |
| load: true | |
| tags: valtronics/frontend:test | |
| - name: Run Trivy vulnerability scanner on backend | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'valtronics/backend:test' | |
| format: 'sarif' | |
| output: 'trivy-backend-results.sarif' | |
| - name: Run Trivy vulnerability scanner on frontend | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'valtronics/frontend:test' | |
| format: 'sarif' | |
| output: 'trivy-frontend-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v2 | |
| with: | |
| sarif_file: 'trivy-backend-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v2 | |
| with: | |
| sarif_file: 'trivy-frontend-results.sarif' | |
| secrets-scan: | |
| name: Secrets Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run Gitleaks | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} | |
| security-tests: | |
| name: Security Tests | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15 | |
| env: | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: test_db | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| run: | | |
| cd backend | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install bandit safety | |
| - name: Run Bandit security linter | |
| run: | | |
| cd backend | |
| bandit -r app/ -f json -o bandit-report.json || true | |
| bandit -r app/ | |
| - name: Run Safety check | |
| run: | | |
| cd backend | |
| safety check --json --output safety-report.json || true | |
| safety check | |
| - name: Upload security reports | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: security-reports | |
| path: | | |
| backend/bandit-report.json | |
| backend/safety-report.json | |
| api-security: | |
| name: API Security Testing | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Compose | |
| run: | | |
| sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose | |
| sudo chmod +x /usr/local/bin/docker-compose | |
| - name: Start services | |
| run: | | |
| cp .env.example .env | |
| docker-compose up -d | |
| sleep 60 | |
| - name: Install OWASP ZAP | |
| run: | | |
| wget https://github.com/zaproxy/zaproxy/releases/download/v2.13.0/ZAP_2.13.0_Linux.tar.gz | |
| tar -xvf ZAP_2.13.0_Linux.tar.gz | |
| chmod +x ZAP_2.13.0/zap.sh | |
| - name: Run OWASP ZAP Baseline Scan | |
| run: | | |
| ./ZAP_2.13.0/zap.sh -cmd -quickurl http://localhost:8000 -quickprogress -quickout zap-report.html || true | |
| - name: Upload ZAP report | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: zap-report | |
| path: zap-report.html | |
| - name: Cleanup | |
| if: always() | |
| run: | | |
| docker-compose down -v | |
| compliance-check: | |
| name: Compliance Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Run compliance checks | |
| run: | | |
| # Check for hardcoded credentials | |
| echo "Checking for hardcoded credentials..." | |
| grep -r -i "password\|secret\|key\|token" --include="*.py" --include="*.js" --include="*.json" --include="*.yaml" --include="*.yml" . | grep -v "node_modules\|.git\|__pycache__" || true | |
| # Check for insecure configurations | |
| echo "Checking for insecure configurations..." | |
| grep -r "DEBUG.*True\|allow_anonymous.*true" --include="*.py" --include="*.yaml" --include="*.yml" . || true | |
| # Check for exposed endpoints | |
| echo "Checking for exposed endpoints..." | |
| grep -r "0.0.0.0\|0.0.0.0:8000" --include="*.py" --include="*.yaml" --include="*.yml" . || true | |
| - name: Check license compliance | |
| run: | | |
| # Install license checker | |
| pip install pip-licenses | |
| # Check backend licenses | |
| cd backend | |
| pip-licenses --from=mixed --format=table --ignore-packages | |
| # Check frontend licenses | |
| cd ../frontend | |
| npm install -g license-checker | |
| license-checker --onlyAllow 'MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC' || true | |
| security-report: | |
| name: Security Report | |
| needs: [codeql, dependency-scan, container-scan, secrets-scan, security-tests, api-security, compliance-check] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v3 | |
| - name: Generate security summary | |
| run: | | |
| echo "# Security Scan Summary" > security-summary.md | |
| echo "" >> security-summary.md | |
| echo "## Scan Results" >> security-summary.md | |
| echo "" >> security-summary.md | |
| # Add results from each scan | |
| echo "- CodeQL: ${{ needs.codeql.result }}" >> security-summary.md | |
| echo "- Dependency Scan: ${{ needs.dependency-scan.result }}" >> security-summary.md | |
| echo "- Container Scan: ${{ needs.container-scan.result }}" >> security-summary.md | |
| echo "- Secrets Scan: ${{ needs.secrets-scan.result }}" >> security-summary.md | |
| echo "- Security Tests: ${{ needs.security-tests.result }}" >> security-summary.md | |
| echo "- API Security: ${{ needs.api-security.result }}" >> security-summary.md | |
| echo "- Compliance Check: ${{ needs.compliance-check.result }}" >> security-summary.md | |
| - name: Upload security summary | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: security-summary | |
| path: security-summary.md | |
| - name: Comment on PR with security results | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v6 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const summary = fs.readFileSync('security-summary.md', 'utf8'); | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: summary | |
| }); |