SecureChain

User guide

CI/CD

Recipes for a pipeline that already sends a scan: pick the right token, choose a gate, check pull requests, record releases, scan a monorepo, and send the results to other tools. For the first job, see Get started.

Pick a token for the pipeline #

Use the smallest token that does the job. If it leaks, less is exposed.

Your pipelineWho makes the tokenWhat to select on Access tokens
The pipeline of one repositoryAn adminThe CI token (one repository) preset and the repository. The token can send and read that repository only. It expires in 90 days.
A CI server that builds many repositories of one teamAn adminScope a department, the department, and the CI upload rights. A scan of a new repository puts the repository in that department.
Any pipeline, when you are not an adminA memberThe CI upload rights. The token acts as you: it stops when your user is disabled.

Access tokens explains each right and scope.

Choose the gate #

CommandThe job fails whenUse it on
securechain scaNever. It only reports.Any branch, to keep the portal current.
securechain sca --fail-on highAn open finding is high or critical. The other levels are critical, medium, and low.The default branch and the release branches.
securechain compare --base main --fail-on-newThe branch has an open finding that the latest scan of main does not have.Pull requests and merge requests. See Pull and merge requests.
securechain checkA project that uses TuxCare builds is not in the state that harden made.Projects that use TuxCare builds. See Fix vulnerabilities.

Pull and merge requests #

A pull request often inherits old findings from the base branch. compare --fail-on-new fails it only on the findings that it adds. The base branch needs a scan of its own, so scan the base branch on each push too.

GitHub Actions:

name: securechain
on:
  push:
    branches: [main]
  pull_request:
jobs:
  securechain:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Scan the branch
        if: github.event_name == 'push'
        uses: TuxCare/securechain-action@v0
        with:
          command: sca
          args: --fail-on high
          portal-token: ${{ secrets.SECURECHAIN_PORTAL_TOKEN }}
          registry-login: none
      - name: Fail on new findings
        if: github.event_name == 'pull_request'
        uses: TuxCare/securechain-action@v0
        with:
          command: compare
          args: --base ${{ github.base_ref }} --fail-on-new
          portal-token: ${{ secrets.SECURECHAIN_PORTAL_TOKEN }}
          registry-login: none

GitLab CI:

securechain:
  image: node:22
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    - curl -fsSL https://securechain.tuxcare.com/get/securechain | sh
    - securechain sca --fail-on high

securechain-new-findings:
  image: node:22
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - curl -fsSL https://securechain.tuxcare.com/get/securechain | sh
    - securechain compare --base "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --fail-on-new

Jenkins (multibranch pipeline): CHANGE_TARGET is set for a pull request build.

sh '''
  curl -fsSL https://securechain.tuxcare.com/get/securechain | sh
  export PATH="$HOME/.local/bin:$PATH"
  if [ -n "$CHANGE_TARGET" ]; then
    securechain compare --base "$CHANGE_TARGET" --fail-on-new
  else
    securechain sca --fail-on high
  fi
'''

The portal files the scan of a pull request under the branch that it comes from. The portal sends alerts for the default branch and the supported releases only, so a feature branch sends none.

Record a release #

A release is the list of packages of a build that you ship. The portal keeps it, checks it against each new advisory, and can export it as a VEX file. Record it from the job that builds the release:

securechain sca --release "$CI_COMMIT_TAG"           # GitLab
securechain sca --release "$GITHUB_REF_NAME"         # GitHub, on a tag push
securechain sca --release "$TAG_NAME"                # Jenkins, with tag discovery on

With the GitHub action, pass the name in args, for example args: --release ${{ github.ref_name }}. The action gives args to the CLI as a list of words, with no shell. Use the action of release 0.1.19 or later.

More than one project in a repository #

Send the results to other tools #

FormatCommandFor
SARIFsecurechain sca --output sarif > securechain.sarifGitHub code scanning and other code-scanning tools.
JSONsecurechain sca --output json > findings.jsonYour own scripts. The JSON format is stable and has a schema_version.
Markdownsecurechain sca --output markdown > findings.mdA comment on a pull request, or a job summary.
JUnitsecurechain check --output junit > report.xmlThe test report of GitLab and Jenkins.

To upload the SARIF file to GitHub code scanning, add this step after the scan. The job needs the permission security-events: write:

      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: securechain.sarif

To read the findings from a dashboard, use the REST API.

Pin the CLI version #

The install script installs the newest release. To run the same release in each job, pin it:

Install methodHow to pin
Install scriptSet SECURECHAIN_VERSION=v0.1.22 before the script.
GitHub ActionPin the action tag, or set the input version.
GitLab CI/CD componentPin the component version, or set the input version.
DockerUse a version tag, for example tuxcare/securechain:0.1.22, not latest.

When the CLI is two or more minor releases behind, it prints a warning. When it is older than the portal accepts, it stops and tells you to upgrade. See Upgrade the CLI.

Exit codes in CI #

CodeMeaningWhat to do
0The run finished. No finding failed the gate.Nothing.
1A finding failed the gate.Read the findings in the job log or in the portal.
2A wrong option, a configuration file that the CLI cannot read, or no package manager that it knows.Read the message.
3No token, or the portal refused it.Check the secret variable. See Troubleshooting.
4The portal did not answer in time.Run the job again, or use --on-portal-error warn.

Exit codes lists every code.

Next: Portal