Platform-native vs third-party scanner integration

Both GitHub and GitLab offer built-in security scanning, but they differ significantly in what is included at which tier and how results surface in the developer workflow.

  • GitHub: Code Scanning (CodeQL + SARIF), Dependabot, and Secret Scanning are available on public repos for free. Private repos require GitHub Advanced Security (GHAS), which is bundled with GitHub Enterprise.
  • GitLab: SAST, DAST, SCA, Container Scanning, and Secret Detection are built-in features. Basic tiers get report artefacts; blocking MR gates require GitLab Ultimate.
  • Third-party scanners (Semgrep, Snyk, AquilaX, Trivy) integrate with both platforms via SARIF uploads, status checks, or platform-specific integrations. These are often preferable for custom rules, multi-language coverage, and cross-platform consistency.

SARIF is the integration standard: The Static Analysis Results Interchange Format (SARIF) is a JSON schema supported by both GitHub and GitLab for uploading findings from external scanners. Any scanner that outputs SARIF can integrate with both platforms without custom glue code.

GitHub: complete security pipeline

A complete GitHub security pipeline covering SAST, SCA, secrets, and IaC in a single workflow file:

.github/workflows/security.ymlyaml
name: Security Scan
on:
  push: { branches: [main, develop] }
  pull_request:

jobs:
  sast:
    runs-on: ubuntu-latest
    container: { image: semgrep/semgrep }
    steps:
      - uses: actions/checkout@v4
      - run: semgrep scan --config=auto --sarif --output=sast.sarif .
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: sast.sarif }

  secrets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }  # full history for secret scan
      - run: |
          pip install trufflehog3
          trufflehog3 --format json --output secrets.json .

  sca:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
          grype dir:. --fail-on critical --output sarif > sca.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: sca.sarif }

  iac:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aquasecurity/trivy-action@master
        with:
          scan-type: config
          format: sarif
          output: iac.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: iac.sarif }

GitHub Code Scanning and SARIF results

Once SARIF is uploaded, findings appear in the Security β†’ Code scanning alerts tab and as inline annotations on pull request diff views. This is the most developer-friendly surface: reviewers see security findings alongside the code change that introduced them.

Branch protection rules: SARIF uploads alone do not block merges. To block PRs with findings, add a required status check in branch protection settings. The SAST job must exit with a non-zero code on findings, not just upload the SARIF artefact.

GitLab: security templates and built-in scanning

GitLab's security templates are the fastest path to full pipeline coverage:

.gitlab-ci.yml β€” full security coverageyaml
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Secret-Detection.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml
  - template: Security/DAST.gitlab-ci.yml

variables:
  SAST_EXCLUDED_PATHS: spec,test,tmp
  SECRET_DETECTION_HISTORIC_SCAN: "true"
  DS_EXCLUDED_ANALYZERS: ""

# Custom AquilaX scan job
aquilax-scan:
  image: aquilax/scanner:latest
  script:
    - aquilax scan --output gl-sast-report.json --format gitlab-sast
  artifacts:
    reports:
      sast: gl-sast-report.json

GitLab MR security widget

When jobs emit artefacts with the correct reports: keys, GitLab automatically aggregates findings and displays them in the Merge Request security widget. This shows:

  • New findings introduced by this MR (not present on the target branch)
  • Fixed findings (present on the target branch but resolved in this MR)
  • Severity breakdown and links to individual finding details

On GitLab Ultimate, you can configure Security Approvals to require a security team member to approve any MR that introduces new critical or high findings β€” before it can merge.

Building security gates that actually block

A security gate is a pipeline job that exits non-zero when findings exceed a policy threshold, causing the CI system to mark the build as failed and block the merge. The key is configuring the right exit conditions:

  • Block on CRITICAL: No exceptions, fix required before merge
  • Warn on HIGH: Opens a ticket, does not block (initially β€” raise to block after backlog is cleared)
  • Secrets found: Always block, regardless of severity. A secret is a secret.

The gradual rollout strategy: Enable all scanners in report-only mode for two weeks. Triage findings, fix the genuine ones, suppress the false positives. Then flip the gate to blocking mode with confidence. This avoids the "day one chaos" of discovering 1,000 pre-existing findings when you enable blocking.

AquilaX: one integration for both platforms

AquilaX provides native integrations for both GitHub and GitLab, with a single CLI that outputs SARIF (for GitHub) or the GitLab security report JSON format. This means consistent rules, thresholds, and suppressions across both platforms β€” critical for organisations that use both.

AquilaX CLI β€” dual-format outputshell
# GitHub Actions: output SARIF for Code Scanning upload
aquilax scan --format sarif --output aquilax.sarif .

# GitLab CI: output GitLab SAST report format
aquilax scan --format gitlab-sast --output gl-sast-report.json .

One scanner, both platforms

AquilaX integrates natively with GitHub and GitLab β€” SARIF uploads, MR comments, security gates, and a central dashboard across all your repositories.

See all integrations β†’