Automating SAST with GitHub Actions and CodeQL

Why CodeQL Belongs in Your DevSecOps Pipeline

Static analysis is most effective when it runs where developers work. GitHub Actions provides native integration with CodeQL, enabling you to:

  • Continuously scan every pull request and main branch commit.
  • Use a curated ruleset aligned with OWASP Top 10 and CWE Top 25.
  • Baseline existing risk so new findings are prioritized.
  • Automate triage with code owners and security champions.

Reference Workflow

The workflow below scans supported languages on a nightly cadence and for every pull request targeting main. It stores the CodeQL database as an artifact for deeper triage when needed.

name: codeql-sast

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]
  schedule:
    - cron: "0 1 * * *" # 01:00 UTC nightly

permissions:
  contents: read
  security-events: write
  actions: read

jobs:
  analyze:
    name: Run CodeQL Analysis
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        language: ["javascript", "python"]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          queries: security-and-quality

      - name: Autobuild
        uses: github/codeql-action/autobuild@v3

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v3
        with:
          category: "/language:${{ matrix.language }}"

      - name: Upload CodeQL Database
        uses: actions/upload-artifact@v4
        with:
          name: codeql-${{ matrix.language }}-database
          path: ${{ runner.temp }}/codeql_databases/${{ matrix.language }}

Pushing Quality Findings to the Right Teams

GitHub converts CodeQL alerts into code scanning findings. Tighten the feedback loop by:

  • Using CODEOWNERS to auto-request reviews from the feature team.
  • Configuring branch protection to require a clean security scan before merging.
  • Routing alerts to Slack or Microsoft Teams via security-events webhooks.

Tip: Leverage GitHub’s autofix beta for supported languages to auto-generate remediation pull requests.

Managing Technical Debt with Baseline Behavior

Legacy code often ships with unresolved findings. Instead of overwhelming developers, baseline the existing alerts:

  1. Run a full scan on main and export alerts with the GitHub Security REST API.
  2. Suppress accepted risks using .codeql/suppressions.yml with business justification.
  3. Track the delta in a dashboard (e.g., GHAS Security Overview or custom datamart).

Operational Guardrails

To keep scanning fast, deterministic, and secure:

  • Cache CodeQL bundles in an internal artifact registry or GitHub’s built-in cache.
  • Pin actions by commit SHA and enable Dependabot to auto-upgrade.
  • Add permissions block to all jobs and default to read unless a step needs more.
  • Use GitHub-hosted runners for predictable environments; self-hosted runners need additional hardening.

Measuring Success

Add CodeQL coverage and MTTR to your DevSecOps scorecard. Track:

  • Percentage of critical repos with CodeQL enabled.
  • Median time to remediate high-severity findings.
  • False positive rate per workflow run.
  • Reduction in exploitable vulnerabilities across releases.

By automating SAST in GitHub Actions you move security left without overwhelming engineers, keeping the feedback loop predictable and actionable.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top