Skip to content
16CI/CD INTEGRATIONS

Integrate with your pipeline

Gate releases by severity threshold, export SARIF/JSON/HTML artifacts, and keep security checks consistent in CI.

SARIF rule identifiers (engine v0.2+) look like fendix.<category>.<title-slug>. Pipeline baselines or suppressions keyed to older per-instance rule IDs must be regenerated against the new SARIF format.

v0.5+: drop-in GitHub Actions workflow · v0.14+: native GitLab CI & CircleCI templates · v0.16+: pre-commit hook (fendix hook install) & diff-aware scans on every commit

A complete reference GitHub Actions workflow lives at examples/github-actions/fendix-scan.yml scan + cached baseline + SARIF upload + PR summary comment + a --fail-on HIGH gate. Drop it into .github/workflows/ and it works on every PR. For GitLab CI and CircleCI, run fendix init --ci gitlab or fendix init --ci circleci to generate a native config file.

New in v0.7: GitHub App (zero-config PR scans)

Skip the workflow YAML entirely. Install the Fendix GitHub App on a repo and every pull_request opens, synchronises, or reopens triggers a hybrid scan automatically — clone of the head SHA only (no history), fendix scan, then a Markdown PR comment plus a SARIF upload to the Code Scanning tab. Setup: docs/github-app.md covers App registration via app/manifest.yml and self-hosting fendix-app via Dockerfile.app (stateless ~250 MiB image, runs on Fly.io / Cloud Run / Render / Railway / ECS / k8s unchanged).

GitHub Actions

GitHub Actions
- name: Run Fendix scan
  run: |
    fendix scan \
      --url ${{ secrets.API_URL }} \
      --format sarif \
      --fail-on HIGH \
      --baseline ./baseline.json \
      --save-baseline ./baseline.json \
      --output fendix.sarif

- name: Upload SARIF
  if: always()
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: fendix.sarif

GitLab CI

GitLab CI
# v0.14+: generate a native GitLab CI template (saves as .gitlab-ci.yml)
fendix init --ci gitlab

# The generated job (or paste manually):
fendix_scan:
  image: ghcr.io/abdel-rahmansaied/fendix:latest
  script:
    - fendix scan
        --url "$API_URL"
        --format json
        --fail-on HIGH
        --baseline ./baseline.json
        --save-baseline ./baseline.json
        --output fendix.json
  artifacts:
    paths: [fendix.json, baseline.json]

CircleCI

CircleCI
# v0.14+: generate a native CircleCI config (saves as .circleci/config.yml)
fendix init --ci circleci

# The generated orb step (or paste manually):
version: 2.1
jobs:
  security-scan:
    docker:
      - image: ghcr.io/abdel-rahmansaied/fendix:latest
    steps:
      - checkout
      - run:
          name: Fendix scan
          command: |
            fendix scan \
              --url "$API_URL" \
              --code ./src \
              --format sarif \
              --fail-on HIGH \
              --output fendix.sarif
      - store_artifacts:
          path: fendix.sarif

Jenkins

Jenkins
sh '''
  fendix scan \
    --url $API_URL \
    --code ./src \
    --format html \
    --fail-on HIGH \
    --save-baseline ./baseline.json \
    --output fendix.html
'''

Docker Compose

Docker Compose
services:
  fendix:
    image: ghcr.io/abdel-rahmansaied/fendix:latest
    command: >
      scan --url http://api:8080
      --code /workspace/src
      --format json --fail-on HIGH
      --save-baseline /workspace/baseline.json
      --output /workspace/results.json
    volumes:
      - .:/workspace

Jira sync (v0.13.1+)

Jira sync (v0.13.1+)
# Idempotent: creates issues on first run, updates on re-run, skips already-filed
fendix jira \
  --findings fendix.json \
  --project SEC \
  --server https://your-org.atlassian.net

# Environment variables (recommended over flags):
# FENDIX_JIRA_TOKEN=<personal-access-token>
# FENDIX_JIRA_USER=you@example.com
# FENDIX_JIRA_SERVER=https://your-org.atlassian.net
# FENDIX_JIRA_PROJECT=SEC

Slack + Teams alerts (v0.13.1+)

Slack + Teams alerts (v0.13.1+)
# Slack webhook
fendix notify \
  --findings fendix.json \
  --slack-webhook "$SLACK_WEBHOOK_URL"

# Microsoft Teams webhook
fendix notify \
  --findings fendix.json \
  --teams-webhook "$TEAMS_WEBHOOK_URL"

# Both at once, only notify on HIGH+
fendix notify \
  --findings fendix.json \
  --slack-webhook "$SLACK_WEBHOOK_URL" \
  --teams-webhook "$TEAMS_WEBHOOK_URL" \
  --min-severity HIGH

SaaS API & the dashboard

Beyond CI snippets, the Fendix SaaS API lets you launch scans programmatically, read an aggregated dashboard, and — with a self-hosted runner — push scans of private or internal targets straight into your workspace. Authenticate with an X-API-Key (fx_ prefix, Pro plan and up).

Self-hosted runners reach what the cloud can't.

A runner is an agent you host inside your network. It claims queued jobs, runs the engine against private targets, and submits the JSON report back to the dashboard — so internal APIs and white-box code scans land alongside everything else. Requires the Enterprise plan's self_hosted_runners feature.

SaaS API — launch a scan

SaaS API — launch a scan
# Launch a scan via the API (X-API-Key, fx_ prefix, shown once at creation)
curl -X POST https://api.fendix.dev/api/scans \
  -H "X-API-Key: $FENDIX_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "mode": "blackbox", "url": "https://api.example.com", "fail_on": "high" }'

# Poll one scan (returns a {scan, findings} envelope)
curl https://api.fendix.dev/api/scans/$SCAN_ID -H "X-API-Key: $FENDIX_API_KEY"

SaaS API — dashboard overview

SaaS API — dashboard overview
# Workspace overview: totals, severity + category breakdowns, 8-week trend.
# Scope to one org with ?organization=<uuid>, or omit for personal scans.
curl "https://api.fendix.dev/api/dashboard?organization=$ORG_ID" \
  -H "X-API-Key: $FENDIX_API_KEY"
# → { total_scans, total_findings, by_severity, by_category, recent_scans, trend }

Self-hosted runner (Enterprise)

Self-hosted runner (Enterprise)
# Self-hosted runner (Enterprise): scan private/internal targets in-network
# and push results to the dashboard. Register once (org admin) → fxr_ token.
TOKEN="fxr_..."

# Claim the next queued job (atomic) → or 204 No Content
curl -X POST https://api.fendix.dev/api/runners/claim -H "X-Runner-Token: $TOKEN"

# Run the engine locally, then submit the JSON report
fendix scan --code /repo --format json --output report.json
curl -X POST "https://api.fendix.dev/api/runners/jobs/$SCAN_ID/result" \
  -H "X-Runner-Token: $TOKEN" -H 'Content-Type: application/json' \
  --data-binary @report.json