diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..e8bcb4b487 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,154 @@ +# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- .-.-. .-.-. .-.- +# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ / / \ \ / / \ \ / / \ +# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-' `-`-' `-`-' `-`-' +# +# CodeQL +# +# This workflow replaces the GitHub CodeQL extension to support fork PRs. +# The extension doesn't trigger on fork PRs due to security restrictions. +# This workflow uses the pull_request event which works for all PRs. +# +# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- .-.-. .-.-. .-.- +# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ / / \ \ / / \ \ / / \ +# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-' `-`-' `-`-' +name: CodeQL + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + - develop + merge_group: + # Required for GitHub merge queue + branches: + - main + - develop + schedule: + # Run weekly security scans every Monday at midnight UTC + - cron: '0 0 * * 1' + +# Cancel in-progress runs when a new commit is pushed +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +# Minimal permissions for fork PRs +# Results are uploaded to Security tab and posted as checks +permissions: + contents: read + security-events: write + actions: read + +jobs: + analyze: + name: CodeQL Analysis + runs-on: ubuntu-latest + timeout-minutes: 15 + + strategy: + fail-fast: false + matrix: + language: ['javascript-typescript', 'rust'] + + # Skip autobuild - CodeQL can analyze source code directly + # No need to compile or install dependencies for static analysis + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: 'true' + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: none + # Use default queries plus security-extended for more coverage + queries: security-extended + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" + + dockerfile: + name: Dockerfile Lint + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: analyze + + permissions: + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Run Hadolint + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + format: sarif + output-file: hadolint.sarif + no-fail: true + + - name: Upload Hadolint results + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: hadolint.sarif + category: "hadolint" + +# Note: ShellCheck action doesn't natively support SARIF output +# Results will appear in workflow logs + shellcheck: + name: Shell Script Lint + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: analyze + + permissions: + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@2.0.0 + with: + scandir: '.' + format: gcc + severity: warning + continue-on-error: true + + # Final status check job for backwards compatibility with the old CodeQL workflow + CodeQL: + name: CodeQL + runs-on: ubuntu-latest + needs: [analyze, dockerfile, shellcheck] + if: always() + + steps: + - name: Check all jobs succeeded + run: | + if [ "${{ needs.analyze.result }}" != "success" ]; then + echo "CodeQL analysis failed" + exit 1 + fi + if [ "${{ needs.dockerfile.result }}" != "success" ]; then + echo "Dockerfile lint failed" + exit 1 + fi + if [ "${{ needs.shellcheck.result }}" != "success" ]; then + echo "ShellCheck lint failed" + exit 1 + fi + echo "All security checks passed!" +