Remediate codebase health issues #415
Workflow file for this run
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] | |
| paths-ignore: | |
| - 'docs/**' | |
| - 'mkdocs.yml' | |
| - '*.md' | |
| - 'plan/**' | |
| - 'LICENSE' | |
| - '.github/workflows/deploy-docs.yml' | |
| pull_request: | |
| branches: [main, develop] | |
| paths-ignore: | |
| - 'docs/**' | |
| - 'mkdocs.yml' | |
| - '*.md' | |
| - 'plan/**' | |
| - 'LICENSE' | |
| - '.github/workflows/deploy-docs.yml' | |
| schedule: | |
| # Weekly Monday 6 AM UTC - regular security audits | |
| - cron: '0 6 * * 1' | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| # Python dependency vulnerability scanning | |
| pip-audit: | |
| name: Python Dependency Scan (pip-audit) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| security-events: write | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| version: "latest" | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Cache uv dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cache/uv | |
| .venv | |
| key: ${{ runner.os }}-uv-security-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv-security- | |
| ${{ runner.os }}-uv- | |
| - name: Install dependencies | |
| run: uv sync --all-extras --dev | |
| - name: Export locked Python dependencies | |
| run: | | |
| uv export --format requirements-txt --all-extras --dev --no-emit-project --no-hashes > audit-requirements.txt | |
| - name: Run pip-audit | |
| run: | | |
| uv run pip-audit --requirement audit-requirements.txt --vulnerability-service pypi | |
| # Python SAST with Bandit (run directly with uv for proper pyproject.toml support) | |
| bandit: | |
| name: Python SAST (Bandit) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| security-events: write | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| version: "latest" | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Cache uv dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cache/uv | |
| .venv | |
| key: ${{ runner.os }}-uv-bandit-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv-bandit- | |
| ${{ runner.os }}-uv- | |
| - name: Install dependencies | |
| run: uv sync --all-extras --dev | |
| - name: Run Bandit Security Scan | |
| run: | | |
| uv run bandit -r phentrieve api -c pyproject.toml -f sarif -o bandit-results.sarif --severity-level medium --confidence-level medium || true | |
| # Always generate output even if no issues found | |
| if [ ! -s bandit-results.sarif ]; then | |
| echo '{"$schema":"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json","version":"2.1.0","runs":[{"tool":{"driver":{"name":"Bandit","version":"1.9.2"}},"results":[]}]}' > bandit-results.sarif | |
| fi | |
| - name: Upload Bandit results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: bandit-results.sarif | |
| category: bandit | |
| # JavaScript dependency vulnerability scanning | |
| npm-audit: | |
| name: JavaScript Dependency Scan (npm audit) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Run npm audit (production dependencies) | |
| working-directory: frontend | |
| run: npm audit --omit=dev --audit-level=critical | |
| - name: Run npm audit (full report) | |
| working-directory: frontend | |
| run: npm audit --audit-level=high || true | |
| # Don't fail on high for dev deps - many false positives | |
| # Security scan summary | |
| security-summary: | |
| name: Security Summary | |
| needs: [pip-audit, bandit, npm-audit] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Check security scan results | |
| run: | | |
| echo "## Security Scan Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Scan | Result |" >> $GITHUB_STEP_SUMMARY | |
| echo "|------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| pip-audit (Python deps) | ${{ needs.pip-audit.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Bandit (Python SAST) | ${{ needs.bandit.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| npm audit (JS deps) | ${{ needs.npm-audit.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Fail if critical scans failed | |
| if [[ "${{ needs.pip-audit.result }}" == "failure" ]]; then | |
| echo "::error::pip-audit found vulnerabilities in Python dependencies" | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.bandit.result }}" == "failure" ]]; then | |
| echo "::error::Bandit found security issues in Python code" | |
| exit 1 | |
| fi | |
| # npm-audit failure is warning only (many false positives) | |
| if [[ "${{ needs.npm-audit.result }}" == "failure" ]]; then | |
| echo "::warning::npm audit found issues - review recommended" | |
| fi | |
| echo "::notice::Security scans completed" |