Documentation menu

GitHub Action

Run Settlens checks on every pull request or on a schedule, fail the job at your severity threshold and keep the reports as build artifacts.

In short

The Settlens composite GitHub Action runs settlens check against a configuration file, fails the job when a failing check reaches the fail-on severity (default high) and leaves JSON, HTML and SARIF reports for later steps. It runs passive checks only, from a checkout of the private Settlens repository.

On this page

The repository includes a composite GitHub Action (action.yml at its root). It installs Node.js 24, installs Settlens' production dependencies from the lockfile, then runs settlens check against your configuration file. The job fails when a failing check reaches the fail-on severity, and the JSON, HTML and SARIF reports are left in the output directory for later steps.

The Action is not on the GitHub Marketplace: Settlens lives in a private repository that pilot participants receive, so workflows run the Action from a copy of that repository. It runs passive checks only; it has no input for the active probe.

Where the Action sits in a workflow.

Inputs

Read from action.yml. Every input is optional.

Action inputs
InputDefaultPassed to the CLI asDescription
configsettlens.config.json--configPath to a Settlens JSON configuration file.
outputreports--outDirectory for JSON, HTML and SARIF evidence reports.
formatsjson,html,sarif--formatComma-separated report formats.
fail-onhigh--fail-onMinimum failing severity that blocks CI.
allowed-hosts(empty)SETTLENS_ALLOWED_HOSTSComma-separated exact hostnames allowed to receive custom headers.
  • fail-on takes low, medium, high, critical or none. Only failing checks count; warnings never fail the job.
  • allowed-hosts is the allowlist for custom headers in the config. It is deliberately separate from the config file: a pull request that edits the config cannot add a new destination for your secrets without also changing the workflow.
  • config and output are paths relative to the workspace root.

Outputs

Action outputs
OutputDescription
report-directoryDirectory containing the generated evidence.

report-directory is set on every run, including when the gate fails: the step records the exit status of settlens check, writes the output, then exits with that status. The workflows below pass the literal output path to their upload steps.

Workflow in your own repository

Check out the Settlens repository next to your code, pinned to a commit you reviewed, and run the Action from that path. SETTLENS_REPO_TOKEN is a token with read access to the Settlens repository only, such as a fine-grained personal access token or a GitHub App token; the default GITHUB_TOKEN cannot read another private repository.

YAML.github/workflows/settlens.yml
name: Settlens

on:
  pull_request:
  schedule:
    - cron: "17 6 * * 1-5" # weekdays, 06:17 UTC
  workflow_dispatch:

permissions:
  contents: read

jobs:
  x402-assessment:
    runs-on: ubuntu-latest
    steps:
      - name: Check out this repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

      - name: Check out Settlens
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
        with:
          repository: OWNER/SETTLENS-REPOSITORY # the repository shared with your pilot
          ref: FULL-40-CHARACTER-COMMIT-SHA # a Settlens commit you reviewed
          path: .settlens
          token: ${{ secrets.SETTLENS_REPO_TOKEN }} # read-only access to that repository
          persist-credentials: false

      - name: Assess x402 endpoints
        uses: ./.settlens
        with:
          config: settlens.config.json
          output: reports
          fail-on: high
          allowed-hosts: staging.merchant.example
        env:
          ASSESSMENT_TOKEN: ${{ secrets.ASSESSMENT_TOKEN }} # read by ${ASSESSMENT_TOKEN} in the config

      - name: Upload evidence
        if: always()
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
        with:
          name: settlens-reports
          path: reports/
          if-no-files-found: error
          retention-days: 30

The schedule turns the same job into a recurring check of production endpoints. To compare each run with the previous one and alert only on changes, use Monitor instead.

Workflow in the Settlens repository

When the workflow lives in the repository that contains Settlens at its root, the Action is simply uses: ./. This is the shape of the example shipped in the repository (examples/github-workflow.yml), where the allowlist comes from a repository variable:

YAML.github/workflows/settlens.yml
name: Settlens

on:
  pull_request:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  x402-assessment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

      - name: Assess x402 endpoints
        uses: ./
        with:
          config: settlens.config.json
          fail-on: high
          allowed-hosts: ${{ vars.SETTLENS_ALLOWED_HOSTS }}

      - name: Upload evidence
        if: always()
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
        with:
          name: settlens-reports
          path: reports/
          if-no-files-found: error
          retention-days: 30

Secrets and custom headers

When a target needs authentication, reference the secret from the config as ${NAME}, provide it to the step as an environment variable, and list the target's hostname in allowed-hosts. Settlens refuses to send any custom header to a host that is not on that list, and it never writes header values to reports. See Headers and secrets.

Workflows triggered by pull_request from a fork do not receive repository secrets, so targets that need them cannot be assessed on fork pull requests.

SARIF and code scanning

The SARIF file lists failing and warning checks, one rule per check id (format details in Reports).

Settlens findings concern a URL, not a line of code, but code scanning only displays results that have a location. Each result is therefore anchored at line 1 of the file named by the config input, so the alerts appear on your configuration file, with the target URL in the message. Each target gets its own fingerprint, so the same check failing on two endpoints stays two alerts.

Code scanning on private repositories

On private repositories, code scanning requires GitHub Code Security; without it the upload fails. The findings are also in the job status, the console summary and the uploaded JSON and HTML reports.

To upload the file, the job needs the security-events: write permission, and the condition below skips fork pull requests, whose token cannot write security events:

YAMLOptional SARIF upload step
# Add to the job: permissions: { contents: read, security-events: write }
      - name: Upload SARIF
        if: >-
          always() &&
          hashFiles('reports/**/*.sarif') != '' &&
          (github.event_name != 'pull_request' ||
          github.event.pull_request.head.repo.full_name == github.repository)
        uses: github/codeql-action/upload-sarif@7188fc363630916deb702c7fdcf4e481b751f97a
        with:
          sarif_file: reports

Permissions

  • contents: read is enough to run the Action and upload artifacts.
  • Add security-events: write only to the job that uploads SARIF.
  • The Action needs no wallet, no private key and no write access. Settlens itself contacts only the targets and facilitators in your config; installing its dependencies contacts the npm registry.

Pinning

  • Pin the Settlens checkout to a full commit SHA (ref:), never a branch, so a change to the repository cannot change what runs in your CI without a review.
  • Pin every third-party action to a full 40-character commit SHA. action.yml itself pins actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e and Node.js 24.
  • Dependencies come from the lockfile with npm ci --prefix "$GITHUB_ACTION_PATH" --omit=dev --ignore-scripts: exact versions, no development dependencies and no install scripts.
  • Keep allowed-hosts in the workflow or in a repository variable, never in the config file it protects.

Next: tune the configuration, look up findings in the check catalog, or request a pilot to get access to the repository.

Sources

  1. Creating a composite actionGitHub Docs · docs.github.com
  2. Secure use reference (pin actions to a full-length commit SHA)GitHub Docs · docs.github.com
  3. SARIF support for code scanningGitHub Docs · docs.github.com

Last updated