GitHub Actions

A security gate that checks the whole box, not just the image.

Drop jakelamon/keelix@v0.1.0 into your pipeline. In one step it scans your Docker Compose stack — host config, port exposure, and AI-agent/MCP posture — and blocks the promote-to-production job when a critical finding or a sub-threshold posture score is present.

Quick start

.github/workflows/deploy.yml — minimal gate
jobs:
  security-gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Keelix posture gate
        uses: jakelamon/keelix@v0.1.0
        with:
          compose: docker-compose.yml

The action fails (exit 1) when any critical finding is present. The full list of inputs is below — you can add outside-in probing, a baseline file for delta gating, and a posture report artifact.

Inputs reference

InputRequiredDefaultDescription
composeyesdocker-compose.ymlPath to the docker-compose.yml to audit
hostno(empty)Host to probe outside-in. Leave empty for static analysis only.
no-probenotrueDisable outside-in probing (default on; set false + host to enable)
firewallno(empty)Path to a UFW/iptables rules dump to correlate
baselineno(empty)Path to a previous scan JSON; fail only on NEW criticals
versionnolatestKeelix CLI version to install
reportno(empty)Write a posture report artifact: md, html, or pdf

Output: json— path to the machine-readable scan result JSON written to the runner's temp directory. Pass it to downstream steps or upload as an artifact.

Two-step rollout: monitoring then enforcement

Monitoring mode — build always passes
      - name: Keelix posture scan (monitor)
        uses: jakelamon/keelix@v0.1.0
        continue-on-error: true
        with:
          compose: docker-compose.yml
          report: html

      - name: Upload posture report
        uses: actions/upload-artifact@v4
        with:
          name: keelix-report
          path: ${{ runner.temp }}/keelix-report.html
Enforcement mode — delta gate on new criticals only
      - name: Restore baseline
        uses: actions/cache@v4
        with:
          path: keelix-baseline.json
          key: keelix-baseline-${{ github.ref_name }}

      - name: Keelix posture gate (enforce)
        uses: jakelamon/keelix@v0.1.0
        with:
          compose: docker-compose.yml
          baseline: keelix-baseline.json

      - name: Save new baseline
        run: cp ${{ runner.temp }}/keelix-scan.json keelix-baseline.json

What image-only actions cannot catch

Full pipeline: Trivy image scan + Keelix box gate

.github/workflows/deploy.yml — full example
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Trivy image scan
        uses: aquasecurity/trivy-action@0.35.0   # pin to SHA in prod
        with:
          image-ref: myapp:${{ github.sha }}
          exit-code: "1"
          severity: CRITICAL

  deploy-to-staging:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # … your staging deploy steps …

      - name: Keelix posture gate
        uses: jakelamon/keelix@v0.1.0
        with:
          compose: docker-compose.yml
          report: html

      - name: Upload posture report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: keelix-posture-report
          path: ${{ runner.temp }}/keelix-report.html

  promote-to-production:
    needs: deploy-to-staging
    runs-on: ubuntu-latest
    steps:
      # … promotion only runs if the gate passed …

Frequently asked

How do I add a security gate to GitHub Actions?
Add a step after your deploy-to-staging job that runs `uses: jakelamon/keelix@v0.1.0` with your compose file path. The action installs the Keelix CLI, runs keelix scan --ci against the stack, and exits non-zero if a critical finding is present. Your workflow fails and the promote-to-production job is blocked until the finding is resolved.
What does the Keelix GitHub Action scan that image-only actions miss?
Image scanners like trivy-action check CVEs inside container layers. They cannot see host config, open port bindings, or the AI agents and MCP servers deployed on the same box. Keelix checks all of those: whether an MCP server auto-approves all tool calls, whether a plaintext API key is sitting in a Claude Code or Cursor config file, whether a port is accidentally bound to 0.0.0.0, and how all of it rolls up to a 0–100 posture score. None of those findings live in an image layer.
What is the difference between monitoring and enforcement in a CI security gate?
Monitoring runs the scanner, collects results, and surfaces a report — but the build passes regardless of findings. Enforcement adds --ci to the scan command and sets an exit code policy: the build fails if a critical finding is present or if the posture score falls below your threshold. Most teams start with monitoring to establish a baseline, then switch to enforcement once they have cleared the initial findings.
Can I fail only on new findings instead of every finding?
Yes. Pass a saved baseline JSON from a previous scan via the `baseline` input. The action will only gate on findings that are new relative to that baseline — useful when you are managing a backlog of known issues and want the gate to catch regressions without failing on findings you already know about.
Does the Keelix Action send any data outside my runner?
No. The action installs the Keelix CLI binary into the runner's temp directory, runs the scan entirely on-runner, and writes the result to a local JSON file. No scan data, no secrets, no posture score leaves the runner. The CLI is Apache-2.0 and the source is public at github.com/jakelamon/keelix.

Gate your next deploy in under five minutes.

Free, local-first, Apache-2.0. The CLI runs locally; the Action runs on-runner. Nothing leaves your box.

operator@host — keelix
# install — free & open source (Apache-2.0)
$ curl -fsSL https://keelix.dev/install.sh | sh
$ keelix scan