Skip to content

Integrate with your pipeline

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

Current execution scope

Runtime
Prebuilt Go binaries do not require a Go compiler for basic scanning. Building from source requires Go 1.25+. Optional analyzers have their own runtime requirements; inspect coverage to confirm they actually ran.
DAST
URL and API probing inspect observable runtime behavior. Intrusive probes require --enable-active. An HTTP 200 response alone does not prove access to sensitive data.
SAST
Native static rules cover supported Go, JavaScript, Java and infrastructure patterns. Semgrep and the opt-in Python engine extend applicable checks. Language support does not imply complete framework or path coverage.
SCA
Go analysis uses govulncheck. Python and npm dependency scanners use supported manifests and lockfiles, including poetry.lock, Pipfile.lock and package-lock.json. Advisory queries can transmit package names and versions.
Evidence and policy
Correlation connects supported matching observations; not every finding has multiple sources. Strong single-source evidence can be sufficient. Severity, confidence, finding disposition and release recommendation are distinct.
Coverage and human review
An analyzer failure or missing required evidence can leave the release incomplete. A PASS is a result under the declared policy and coverage, not a guarantee of security or a human approval.

Benchmark tables below are historical, scoped observations. Counts and synthetic regression scores are not production precision/recall. No replacement measurements are claimed here.

Read deployment-specific data handling

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. v3.0 changes finding identity again: re-save any baseline, rewrite any .fendix-ignore rule pinning a fingerprint: value, and expect GitHub alerts to re-file once under their new rule names. Rules matching by path, category or rule id are unaffected.

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
# Generate a native GitLab CI template (saves as .gitlab-ci.yml)
fendix init --ci gitlab

# The generated job (or paste manually):
fendix_scan:
  image: fendixapp/fendix:3.4.1
  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
# 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: fendixapp/fendix:3.4.1
    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: fendixapp/fendix:3.4.1
    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