← Back to all posts

Run Blue Lantern Scans in GitHub Actions

Pipeline-time scanning is where you want this. Running a scanner against your repo manually catches today's secrets but doesn't catch the ones that get added next week. Wired into Actions, every push gets the same check, and findings show up where developers are already looking — on the PR.

This is a drag-and-drop GitHub Actions workflow that runs our secret scanner on every push to a configured branch and surfaces any findings as warnings (no build break).

Prerequisites

  • A provisioned Blue Lantern API key, stored as a repo secret named API_KEY.
  • Enough credits in your account to run the scan. The maximum spend per scan is 1000 credits.
  • The branch you want to scan, configured under on.push.branches in the workflow below. Run this on a pre-production branch so findings are caught before they ship.

What the workflow does

  1. Downloads the Blue Lantern scanner using your API key.
  2. Loads the scanner image into the runner's Docker daemon.
  3. Configures permissions so the runner and the scanner can share a working directory.
  4. Loads 1000 credits onto the scanner instance.
  5. Runs the secret scan against the checked-out repo.
  6. Reads the result file and emits a GitHub ::warning:: for each finding.

The workflow

name: Scan for Secrets using Blue Lantern Security

on:
  push:
    branches:
      - test-branch

jobs:
  build-and-upload:
    runs-on: ubuntu-latest
    permissions:
      contents: read

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

    - name: Download and run scan
      run: |
        # Step 1: fetch the Blue Lantern agent using the API key from secrets
        RESPONSE=$(curl -X GET https://api.bluelanternsecurity.io/on-premises-agent/amd \
          -H "Authorization: ${{ secrets.API_KEY }}")
        RESULT_URL=$(echo $RESPONSE | jq -r '.result.url')
        curl -L "$RESULT_URL" -o bluelantern-amd.zip
        unzip bluelantern-amd.zip
        cd ./release-amd

        # Step 2: load the scanner into Docker
        TARBALL=$(find . -maxdepth 1 -name "bluelantern-scanner*.tar" -print -quit 2>/dev/null)
        docker load -i "$TARBALL"

        # Step 3: shared working directory the runner and scanner can both write to
        DOCKER_USER=$(docker run --rm --entrypoint id bluelantern/scanner:latest -u)
        mkdir -p ${{ runner.temp }}/bluelantern
        sudo setfacl -R -m u:$(whoami):rwx,u:$DOCKER_USER:rwx ${{ runner.temp }}/bluelantern
        sudo setfacl -R -d -m u:$(whoami):rwx,u:$DOCKER_USER:rwx ${{ runner.temp }}/bluelantern

        # Step 4: install with auto-approve and default settings
        printf "\n\n${{ runner.temp }}/bluelantern\nY\n\n\n\n" | ./macos_installer.sh
        cd ..

        # Step 5: load 1000 credits — the maximum required for one scan
        printf ${{ secrets.API_KEY }} | docker run --rm \
          -i -v ${{ runner.temp }}/bluelantern:/data \
          bluelantern/scanner:latest \
          credit-reload enable --amount 1000 --api-key

        # Step 6: run the scan and surface findings as warnings
        RESULTS=$(printf "Y\n" | docker run --rm -i \
          -v ${{ runner.temp }}/bluelantern:/data \
          -v ${{ github.workspace }}/:/workspace:ro \
          bluelantern/scanner:latest run secret-scanner)
        RESULTS_FILE=$(find ${{ runner.temp }}/bluelantern/results -name "*.json" -print -quit)
        FINDINGS=$(jq -r '.results_count // 0' "$RESULTS_FILE")

        if [ "${FINDINGS:-0}" -gt 0 ]; then
          echo "::warning::Secret scanner found $FINDINGS secret(s) in the codebase"
          jq '.results[] | "::warning file=\(.file_path),line=\(.line_start)::\(.description)"' -r "$RESULTS_FILE"
        fi

Notes

  • The workflow uses warnings rather than errors so it doesn't block developers mid-flow. Swap ::warning:: for ::error:: if you want findings to fail the build.
  • For multiple scan types (secrets + malware, etc.), repeat steps 5 and 6 with the appropriate scan command — credit caps apply per scan.

That's the whole loop. Push, scan, see the results inline on the PR.