Skip to content

Enforce one release decision in every pipeline

Fendix runs inside your CI/CD, collects or imports the security evidence, checks the coverage you require, applies the release policy committed in your repository, and returns a result the pipeline can enforce — the same way in every repository.

What happens in the pipeline

Seven steps run on every pull request or merge. The scanner steps produce evidence; the policy steps turn it into a result.

  1. 1

    CI/CD job

    A job on pull request or merge runs the Fendix engine from the signed container image or binary.

  2. 2

    Collect or import evidence

    Fendix's own DAST, SAST, SCA and secrets analysis, plus SARIF from tools you already run through fendix import.

  3. 3

    Validate required coverage

    Every analyzer reports whether it ran. --fail-on-coverage-gap or --require-analyzers fail the job when required evidence is missing.

  4. 4

    Evaluate findings and risk disposition

    Confidence gating, test-code handling, baselines and .fendix-ignore suppressions with expiry dates.

  5. 5

    Apply the release policy

    The threshold and confidence enforcement committed in .fendix.yaml, reviewed like any other change.

  6. 6

    Return an enforceable result

    The CLI marks each finding BLOCK, WARN or INFO and sets the exit code. The hosted workspace turns the same evidence into one decision: PASS, WARN, BLOCK or INCOMPLETE.

  7. 7

    Publish the record

    SARIF 2.1.0 for code scanning, JSON for automation, HTML for people. Hosted decisions are stored with their rationale and policy version.

What the exit code means

0
Nothing reached BLOCK under your policy.
1
At least one finding reached BLOCK. The report says which, and why.
2
The run could not produce a trustworthy result: an error, or a required coverage gap when you enabled the coverage flags.

By default, severity alone does not fail the job: a finding at or above --fail-on blocks only when its deterministic confidence and evidence support the claim, and every finding held at WARN says why. --enforce-confidence=false restores the legacy severity-only gate, and a finding that blocks only because of it is marked as a policy override.

How policy and confidence decide a block

GitHub Actions: Fendix Security Scan

The recommended GitHub integration: a public GitHub Marketplace Action that installs a signature-verified Fendix release and gates the job on your release policy.

Pin the Action to the full commit of its v3.7.0 release, with an explicit version. The commit fixes the Action's own code, which cannot change under you; version selects the engine release it installs, here v3.7.0. Never reference @main; it changes without review.

.github/workflows/fendix.yml
permissions:
  contents: read
  security-events: write   # SARIF upload
  actions: read            # SARIF upload in a private or internal repository

steps:
  - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
    with:
      fetch-depth: 0       # diff mode compares against the PR base ref
  - uses: Fendix-app/Fendix@90adf6a5082be0661b4156566a3a99609ed4792d # v3.7.0
    with:
      version: v3.7.0
      code: .
      fail-on: HIGH
Fendix Security Scan on GitHub Marketplace

Required analyzers

For a code scan the Action requires Semgrep. It runs Semgrep on a bundled rule before the scan and passes the requirement to the engine, so a missing, broken or hung Semgrep fails the job with exit 2 instead of letting it pass without Semgrep. Semgrep needs glibc 2.34 or later, or musl 1.2 or later, on x86_64 or aarch64; GitHub-hosted runners and the official image qualify. On an older self-hosted runner, run Fendix from the official image in a container job, or set require-analyzers: none to scan without Semgrep, and the gate then warns that coverage is not enforced.

The @v1 tag

Since 2026-10-27, @v1 resolves to the v3.7.0 release commit, the same Action code as the pin above, and literal @v1 with version: v3.7.0 passed the same end-to-end scenarios. The tag moves when a later compatible release is published, so pin the commit when the reference must never change.

Private repositories

SARIF upload to a private or internal repository requires GitHub Code Security. Without it, set upload-sarif: 'false': the scan and the release gate still run.

Pipeline recipes

Copy a recipe, then commit the policy in .fendix.yaml so every pipeline reads the same gate. Code is not localized.

GitLab CI

GitLab CI
# Generate a native GitLab CI include file (.gitlab-ci.fendix.yml)
fendix init --ci gitlab

# The generated job (or paste manually):
fendix_scan:
  image: fendixapp/fendix:3.7.0
  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 snippet (.circleci/fendix-config.yml)
fendix init --ci circleci

# The generated orb step (or paste manually):
version: 2.1
jobs:
  security-scan:
    docker:
      - image: fendixapp/fendix:3.7.0
    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.7.0
    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 issue sync

Jira issue sync
# Required Jira configuration
export FENDIX_JIRA_URL=https://your-org.atlassian.net
export FENDIX_JIRA_PROJECT_KEY=SEC
export FENDIX_JIRA_EMAIL=you@example.com
export FENDIX_JIRA_API_TOKEN=<personal-access-token>

# Optional severity floor (default: HIGH)
export FENDIX_JIRA_MIN_SEVERITY=HIGH

# Idempotent: creates once, then skips an existing fendix-id label
fendix jira --findings fendix.json

Slack and Microsoft Teams alerts

Slack and Microsoft Teams alerts
# Configure either or both incoming webhooks
export FENDIX_SLACK_WEBHOOK_URL="$SLACK_WEBHOOK_URL"
export FENDIX_TEAMS_WEBHOOK_URL="$TEAMS_WEBHOOK_URL"

# Optional severity floor (default: CRITICAL)
export FENDIX_NOTIFY_MIN_SEVERITY=HIGH

fendix notify --findings fendix.json

Generated workflows and the GitHub App

fendix init --ci github, --ci gitlab or --ci circleci writes a native workflow that installs a pinned Fendix release and verifies its signature before running. The GitLab workflow keeps the SARIF file as an ordinary artifact, since Fendix SARIF is not GitLab's SAST report format.

Prefer to own the workflow file? The tested reference workflow is an alternative for teams that want direct workflow ownership, an immutable container digest and explicitly pinned third-party Actions. It runs the official v3.7.0 container and includes a cached baseline, SARIF upload, a PR summary comment and a --fail-on HIGH gate: examples/github-actions/fendix-scan.yml

Prefer no workflow file? A self-hosted GitHub App scans each pull request and posts a summary comment plus SARIF annotations. Setup and deployment are documented in docs/github-app.md

Technical reference: Require coverage before a release · What each exit code means · SARIF export for code scanning · Import SARIF from other scanners

Hosted workspace and private targets

The hosted workspace stores scan history, findings, and release decisions. Its backend HTTP routes are a private service interface, so supported automation uses the CLI, CI/CD integrations, JSON reports, and SARIF documented above.

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

An Enterprise runner performs target and source analysis inside your network and returns the resulting report to your hosted workspace. Fendix provides the supported runner package and connection values during onboarding; the wire protocol is not a public extension contract.

Customer-facing runner setup

  1. Create or select the Enterprise workspace and request runner enablement through your Fendix contact.
  2. Register the runner from workspace settings and place the one-time connection values in your approved secret store.
  3. Deploy the supported runner package inside the network that can reach the authorized targets, then verify health from the workspace.
  4. Use the documented troubleshooting and support path for connection failures; do not implement a custom client against backend service routes.

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 Python engine attempted by code scans extend applicable checks when available. 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.
Read deployment-specific data handling

Upgrading from an older engine

v3.0 changed how findings are identified, and v3.6.0 applies baselines, .fendix-ignore rules and SARIF identity to each occurrence. After upgrading from before v3.0, re-save baselines once and rewrite any .fendix-ignore rule that pins a fingerprint: value; expect GitHub code-scanning alerts to re-file once under their new rule IDs.