sidebar hamburger menu

SecureChain CLI

securechain is a command-line tool that connects a project to SecureChain and keeps it there. It reads the dependency tree your own package manager resolved, asks the TuxCare catalogue which hardened builds your subscription reaches, writes the pins that select them, reinstalls, and verifies that the tree really changed.

It is one static binary with no runtime of its own. It runs on Linux, macOS and Windows (x86-64 and ARM64), on a developer machine and in CI alike.

Why use it

You can connect a project to SecureChain by hand — the JavaScript page describes every step. The CLI does the same work for you and removes the parts that are easy to get wrong:

  • Finding what is covered. A real project resolves hundreds of packages, most of them transitive. The CLI compares the whole resolved tree with the TuxCare catalogue and tells you which packages have a patched build, which CVEs each build closes, and which ones your subscription does not reach.
  • Transitive dependencies. A vulnerable package is usually not one you declared. The CLI writes the right override for your package manager — overrides, pnpm.overrides, resolutions — so the patched build is selected wherever the package appears in the tree.
  • Lockfiles that keep upstream's bytes. A lockfile pins the exact tarball an install fetches. The CLI refreshes the entries that matter and then verifies the installed tree, so a project never looks hardened while it still installs the unpatched package.
  • Staying hardened. New patched builds are released all the time. securechain check is a gate for CI: it fails the build when a patched build exists and the project is not on it, and securechain update rolls the project forward.
  • Machines with no internet access. The catalogue can be exported on a connected machine and imported on an isolated one, so the same commands work in an air-gapped network.

The CLI never changes anything without telling you what it changed, every writing command has a --dry-run, and a run that cannot verify its own result rolls the project back.

Installation

Prerequisites

  • A TuxCare token — contact [email protected]
  • The package manager your project uses (npm, pnpm, yarn or bun) installed on the machine: the CLI reads the tree that tool resolves
  • Linux, macOS or Windows, x86-64 or ARM64

Choose how you want to install the CLI:

Choose an installation method:

The quickest way on Linux and macOS. The script detects your operating system and architecture, downloads the matching binary, checks its SHA-256 checksum and installs it. It never calls sudo: when /usr/local/bin is not writable, the binary goes to ~/.local/bin.

curl -fsSL https://securechain.tuxcare.com/get/securechain | sh

To install a specific version, or to choose the directory:

curl -fsSL https://securechain.tuxcare.com/get/securechain | SECURECHAIN_VERSION=v0.1.0 SECURECHAIN_INSTALL_DIR="$HOME/bin" sh

On Windows, use the npm, pip (PyPI) or Manual download option.

Check the installation:

securechain version

Usage

The examples below use an npm project. pnpm, yarn and bun projects work the same way — the CLI detects the package manager from the lockfile or the packageManager field in package.json.

  1. Set your token

    Every securechain command reads the token from the TUXCARE_TOKEN environment variable. On your machine, export it in the shell where you run the commands, before the first one. In CI, add it as a masked secret variable of the pipeline — the CLI picks it up from the environment the same way:

    export TUXCARE_TOKEN=<TOKEN>
    

    Replace <TOKEN> with your TuxCare token.

  2. Log in

    securechain auth login
    

    The CLI validates the token and remembers what your subscription covers — SecureChain, ELS, or both. securechain auth status shows it at any time, and securechain auth logout removes it from the machine.

  3. Connect the project — init

    Run it once, in the root of the project:

    securechain init
    

    Output example:

    securechain init
    
      ✓ configuration: .securechain.yaml (created by this run)
      ✓ entitlement:   securechain=true els=true
      ◆ ecosystem:     npm 11.12.1
    
      ✎ wrote: .github/dependabot.yml, .npmrc, .securechain.yaml, renovate.json
    
      ➜ next steps:
        1. commit the files generated by this run. Otherwise, refreshing the lockfile will resolve dependencies from the public npm registry.
        2. run `securechain check` to see what the catalogue covers and what `harden` or `update` would change.
    

    init points the package manager at the TuxCare registry (.npmrc, or .yarnrc.yml for Yarn 2+), writes the project configuration .securechain.yaml, and teaches Dependabot and Renovate not to undo the patched versions. It is safe to run again: it updates what it wrote and keeps every line that is yours. Commit the files it creates.

    Choosing the package manager yourself. Detection needs a lockfile or a packageManager field. If the project has neither yet — a Bun project before its first bun install, for example — name the package manager:

    securechain init --ecosystem bun
    

    The choice is saved in .securechain.yaml, and every later command uses it without being told again. Accepted values: npm, pnpm, yarn-classic, yarn-berry, bun. The --ecosystem flag also works on any single command, for that run only.

  4. Install the dependencies

    The CLI reads the tree your package manager resolved, so the project has to be installed:

    npm install
    
  5. See what the catalogue covers — check

    check reads and never writes. It is the command to run in CI.

    securechain check
    

    Output example:

    securechain check
    
      ⚙ configuration: .securechain.yaml
      ✓ entitlement:   securechain=true els=true
      ◇ catalogue:     17 Sep 2026, 4:04 pm UTC
      ◆ ecosystem:     npm 11.12.1 - 5 components, 2 direct
    
      coverage
        covered_mainstream: 3
        hardenable: 2
    
      findings
        [high][unprotected-with-fix] pkg:npm/[email protected] resolves to the unpatched upstream build; 0.4.2-tuxcare.4 is available to this subscription, closing CVE-2024-47764
          fix: run `securechain harden`
    
      ✖ exit 1 (findings)
    

    Every finding names the package, the patched build and the CVEs it closes, and says which command fixes it. Add --explain to see the evidence behind each finding. securechain status prints the same picture without acting as a gate: findings do not make it fail.

  6. Apply the patched builds — harden

    Preview first. --dry-run prints the exact diff and writes nothing:

    securechain harden --dry-run
    

    Then apply:

    securechain harden
    

    harden pins the patched builds in package.json — directly for the packages you declared, through overrides for transitive ones — refreshes the lockfile, reinstalls, and verifies that the installed tree holds the builds it selected. If the result does not match the plan, every file is restored to what it was.

    Commit package.json and the lockfile together, then run securechain check again: it should now exit 0.

  7. Keep up with new builds — update

    TuxCare keeps releasing patched builds for the versions you are on. When check reports catalogue-drift, roll the project forward:

    securechain update
    

    Output example:

      ✎ wrote: package.json
    
      ℹ notes:
        · pkg:npm/[email protected] moved to 0.4.2-tuxcare.4, the newest build on its base version
        · 1 pin rolled forward across 1 file
    

    update never changes a package's base version — 0.4.2 stays 0.4.2 — so it is a patch, never an upgrade. securechain update --check-only reports what is behind, writes nothing and exits 1, which makes it a second gate for CI.

All commands

CommandWhat it does
securechain initConnects the project: registry configuration, .securechain.yaml, Dependabot and Renovate rules. Run once per repository; safe to re-run.
securechain auth loginValidates the token and remembers what the subscription covers.
securechain auth statusShows what this machine's subscription covers.
securechain auth logoutRemoves the stored token and subscription details.
securechain statusReports what would change. Writes nothing, and findings do not make it fail.
securechain checkThe CI gate. Writes nothing; exits 1 when a patched build exists and the project is not on it.
securechain hardenPins the patched builds, reinstalls and verifies. Rolls back if the result does not match the plan.
securechain updateRolls existing pins forward to the newest patched build of the same base version.
securechain migrateRewrites the legacy npm:@els-js/… alias form to canonical package names, then reinstalls and verifies.
securechain scaInventories the dependencies and reports their known vulnerabilities. Writes nothing.
securechain sca vuln <id>Prints one advisory in full, for example securechain sca vuln CVE-2024-47764.
securechain sbomWrites a CycloneDX or SPDX document from the resolved tree: securechain sbom --output bom.cdx.json.
securechain feed exportPacks the catalogue into one file for a machine with no internet access.
securechain feed import <file>Verifies and loads a catalogue file produced by feed export.
securechain versionPrints the version.
securechain completion <shell>Prints a shell completion script for bash, zsh, fish or powershell.

Every writing command — init, harden, update, migrate — accepts --dry-run.

Options for every command

OptionDefaultMeaning
--dir <path>.The project root.
--ecosystem <name>auto-detectedUse this package manager for this run. With init, the choice is saved.
--feed-max-age <duration>24hHow old the catalogue may be. See below.
--offlineoffNever touch the network. Needs a catalogue already on the machine.
--output <format>humanhuman, json, sarif, junit or markdown.
--token <token>TUXCARE_TOKENThe subscription token. Prefer the environment variable in CI.
--no-coloroffPlain output, with no colours or symbols.
--timeout <duration>10mA deadline for the whole command.

How old the catalogue may be — --feed-max-age. The CLI keeps a copy of the catalogue on the machine and refreshes it when it is older than this value. The default is 24 hours. Pass the flag to choose another value for one run:

securechain check --feed-max-age 24h

To set it for the whole project, pass it to init. The value is written into .securechain.yaml as feed_max_age, and every command reads it from there:

securechain init --feed-max-age 168h

A value on the command line always wins over the one in the file. Durations are written as 36h, 168h and so on.

Using the CLI in CI

check exits 0 when the project is on every patched build it can reach, and 1 when it is not — so it needs no wrapper:

securechain:
  image: node:22-slim
  # TUXCARE_TOKEN comes from the project's CI/CD variables
  script:
    - curl -fsSL https://securechain.tuxcare.com/get/securechain | sh
    - npm ci
    - securechain check --output junit > report.xml
  artifacts:
    reports:
      junit: report.xml

--output sarif feeds GitHub and GitLab code scanning, and --output json is a stable, versioned format to script against.

Exit codeMeaning
0Clean.
1Findings: a patched build exists and the project is not on it. Fail the build.
2Usage: a bad flag, an unreadable configuration, no package manager detected.
3Authentication: the token is missing, expired, or does not cover this.
4Catalogue: it cannot be reached, or the copy on the machine is too old.
5Toolchain: the project is not installed, or the package manager failed.
6Verification failed: the change was rolled back.
7Internal error.

Machines with no internet access — feed export and feed import

The CLI needs the TuxCare catalogue to know which patched builds exist. On an isolated machine — an air-gapped build server, a locked-down CI runner — it cannot download the catalogue, so you carry it across as a file.

  1. On a machine with internet access, export the catalogue

    securechain feed export --fetch
    

    Run inside a project that init has configured, this writes the catalogue for the project's ecosystem to a file named tuxcare-catalog. --fetch downloads the newest catalogue first; without it, the command packs the copy already on the machine.

    Outside a project, or to choose the file name, say both explicitly:

    securechain feed export --ecosystem npm --output ./npm-catalog.tar.zst --fetch
    
  2. Copy the file to the isolated machine

    Use whatever transfer your policy allows. The file is signed by TuxCare, and the signature travels inside it.

  3. Import it

    securechain feed import ./tuxcare-catalog
    

    The CLI verifies the signature before it stores anything. A file that was changed on the way, or one older than the catalogue already on the machine, is refused.

  4. Work offline

    securechain check --offline
    

    --offline tells the CLI never to touch the network. harden and update take it too.

The catalogue's age is counted from the moment TuxCare published it, not from the moment you imported it. With the default --feed-max-age of 24 hours, a file imported today is refused tomorrow. For a transfer you make once a week, set the limit once for the project — securechain init --feed-max-age 168h — and keep in mind what it means: a patched build released during that week is not visible on the isolated machine until the next import.

The isolated machine still needs a way to install the packages themselves — typically an internal mirror of the TuxCare registry. See Managing the SecureChain Repository.

What's next?