Reference
Look up the details here: the ways to install the securechain CLI, its commands, options, exit codes, and configuration file, the access tokens, the REST API, and the MCP server. To set up the CLI for the first time, read Get started.
This page describes version 0.1.22 of the CLI. securechain version prints the version that you have.
Install the CLI #
The CLI is one file. Select the method that fits your computer or your CI job:
For Linux and macOS. The script finds your operating system and processor, downloads the file, checks its checksum, and installs it. It does not need root access.
curl -fsSL https://securechain.tuxcare.com/get/securechain | sh
- The script installs to
/usr/local/binwhen it can write there, else to~/.local/bin. SetSECURECHAIN_INSTALL_DIRto select another directory. - Set
SECURECHAIN_VERSION, for exampleSECURECHAIN_VERSION=v0.1.22, to install one version. See Pin the CLI version. - On Windows, use npm, Python, or Manual download.
For macOS and Linux with Homebrew:
brew install tuxcare/tap/securechain
The package @tuxcare/securechain holds the file for your platform. It downloads nothing when you install it.
npm install --global @tuxcare/securechain
Or run it without an installation:
npx @tuxcare/securechain sca
The package securechain on PyPI holds the file for your platform. pipx and uv keep it out of the environment of your project:
pipx install securechain
Or run it without an installation:
uvx securechain sca
The image tuxcare/securechain is on Docker Hub. Mount your project and pass the token:
docker run --rm -v "$PWD":/work -w /work -e SECURECHAIN_PORTAL_TOKEN tuxcare/securechain:latest-toolchains sca
| Tag | What it holds |
|---|---|
tuxcare/securechain:latest | The CLI only. Use it as a base image, or where your image has the package manager. |
tuxcare/securechain:latest-toolchains | The CLI with npm, mvn, and pip, for a job that has no package manager of its own. |
latest follows the newest release. In CI, pin a version, for example tuxcare/securechain:0.1.22-toolchains.
For Debian and Ubuntu. The TuxCare SecureChain key signs the repository, and the CLI updates with the other packages of the system.
curl -fsSL https://securechain.tuxcare.com/apt/tuxcare-securechain.gpg | sudo tee /etc/apt/keyrings/tuxcare-securechain.gpg >/dev/null
curl -fsSL https://securechain.tuxcare.com/apt/securechain.sources | sudo tee /etc/apt/sources.list.d/securechain.sources >/dev/null
sudo apt-get update && sudo apt-get install -y securechain
For RHEL, AlmaLinux, Rocky Linux, and Fedora. The TuxCare SecureChain key signs the repository.
sudo curl -fsSL -o /etc/yum.repos.d/securechain.repo https://securechain.tuxcare.com/yum/securechain.repo
sudo dnf install -y securechain
On a system without dnf, use yum install -y securechain.
A Java build needs no installation: the plugin downloads the CLI for your platform, checks its checksum, keeps it in ~/.m2, and runs it. Add the TuxCare plugin repository to pom.xml:
<pluginRepositories>
<pluginRepository>
<id>tuxcare</id>
<url>https://artifacts.tuxcare.com/repository/maven-plugin-securechain/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
Then add the plugin inside <build><plugins>:
<plugin>
<groupId>com.tuxcare</groupId>
<artifactId>securechain-maven-plugin</artifactId>
<version>0.1.0</version>
<executions>
<execution><goals><goal>check</goal></goals><phase>verify</phase></execution>
</executions>
</plugin>
Or run it one time, with no change to pom.xml:
mvn com.tuxcare:securechain-maven-plugin:check
The Gradle plugin works as the Maven plugin does: it downloads the CLI for your platform, checks its checksum, keeps it, and runs it. In settings.gradle.kts:
pluginManagement {
repositories {
maven { url = uri("https://artifacts.tuxcare.com/repository/maven-plugin-securechain/") }
gradlePluginPortal()
}
}
In build.gradle.kts:
plugins {
id("com.tuxcare.securechain") version "0.1.0"
}
Then:
./gradlew securechainCheck
Each release is at https://securechain.tuxcare.com/get/<version>/, with checksums.txt, a signature for each file, and the public key securechain.pub. https://securechain.tuxcare.com/get/latest/ always has the files of the newest release.
| Platform | File |
|---|---|
| Linux x86-64 | securechain-linux-amd64 |
| Linux ARM64 | securechain-linux-arm64 |
| macOS Intel | securechain-darwin-amd64 |
| macOS Apple silicon | securechain-darwin-arm64 |
| Windows x86-64 | securechain-windows-amd64.exe |
| Windows ARM64 | securechain-windows-arm64.exe |
For example, on Linux x86-64:
curl -fsSLO https://securechain.tuxcare.com/get/latest/securechain-linux-amd64
curl -fsSLO https://securechain.tuxcare.com/get/latest/checksums.txt
sha256sum --check --ignore-missing checksums.txt
install -m 0755 securechain-linux-amd64 /usr/local/bin/securechain
On Windows, download the .exe file, rename it to securechain.exe, and put it in a directory of your PATH.
macOS quarantines a file that a web browser downloads, and blocks it at the first start. Download the file with curl, as above.
Then check the installation:
securechain version
Upgrade the CLI #
When a newer release is out, the CLI prints a warning on each run that connects to your workspace. When the CLI is older than the oldest version that the portal accepts, the CLI stops and tells you to upgrade. To upgrade, run:
securechain upgrade
upgradefinds the method that installed the CLI. It needs no token and no project.- For Homebrew, npm, pipx, uv, the install script, and a manual download on Linux or macOS, it prints the step and runs it.
- For apt, dnf, Docker, Maven, and Gradle, it prints the step only. Do the step yourself: apt and dnf need root, a Docker image needs a new pull or a new tag, and the Maven and Gradle plugins use the version that your build file names.
| Installation method | Upgrade step |
|---|---|
| Install script | Run the script again. If you set SECURECHAIN_VERSION, set the new version. |
| Homebrew | brew upgrade tuxcare/tap/securechain |
| npm | npm install --global @tuxcare/securechain. With npx, run npx @tuxcare/securechain@latest. |
| Python | pipx upgrade securechain, or uv tool upgrade securechain. With uvx, run uvx securechain@latest. |
| Docker | Pull the image again, for example docker pull tuxcare/securechain:latest-toolchains. For a pinned tag, set a newer version in the CI job. |
| apt | sudo apt-get update && sudo apt-get install --only-upgrade securechain |
| dnf / yum | sudo dnf upgrade --refresh securechain, or sudo yum update securechain |
| Maven, Gradle | Set a newer version of the plugin in the build file. The plugin downloads the CLI of that version. |
| Manual download | Download the file again from https://securechain.tuxcare.com/get/latest/, check it against checksums.txt, and replace the old file. |
| GitHub Action, GitLab CI/CD component | The major tag (@v0, @0) follows the newest release. A pinned tag, or the input version, keeps one release: set a newer one. |
Sign in the CLI #
The CLI uses one secret: an access token of your workspace.
- On your computer
- Run
securechain auth login. The CLI shows a link and a code, and opens the link in your browser. Sign in, check that the page shows the same code, select your workspace, and select Approve. The CLI keeps the token in the keychain of your computer. Over SSH, or on a computer with no browser, open the link on another device. - In CI
- Make a token in the portal and keep it in a masked CI variable with the name
SECURECHAIN_PORTAL_TOKEN. The CLI reads the variable and writes the token nowhere. In a CI job, the browser sign-in stops with exit code 2. See Get started: CI/CD.
| Command | What it does |
|---|---|
securechain auth login | Signs in with the browser, as above. A new sign-in on the same computer revokes the token of the old one. |
securechain auth login --with-token | Asks you to paste a token, in place of the browser sign-in. A token that you pipe to auth login works the same way. |
securechain auth status | Prints the workspace, the portal address, and the subscription of the workspace (the line entitlement). |
securechain auth logout | Removes the token from the keychain, and revokes it when it came from a browser sign-in. It also removes the registry credential that registry login wrote. --keep-token keeps the token valid. --keep-registry keeps the registry credential. |
- The CLI has no option for the token: a token on the command line shows in the process list and in the shell history.
- When
SECURECHAIN_PORTAL_TOKENis set, the CLI uses it, not the token in the keychain. - The CLI finds your workspace from the token. The portal address is
https://sc.tuxcare.cloud. You do not type the address of your workspace. - A browser sign-in makes a token with the name
CLI login: computer
on the Access tokens page. The token has your role. - To make sure that a job sends to the correct workspace, set
--tenant name, the variableSECURECHAIN_TENANT, or the keytenantin.securechain.yaml. When the token belongs to another workspace, the CLI stops with exit code 3 and sends nothing.
Commands #
| Command | What it does | What it changes |
|---|---|---|
sca | Sends the package list of the project to your workspace and prints the findings. | Nothing |
sca vuln <id> | Prints one advisory in full, as your workspace has it. For example securechain sca vuln CVE-2024-0001. | Nothing |
compare | Sends the scan and prints the findings that the latest scan of a base branch does not have. Use it for a pull request. See Pull and merge requests. | Nothing |
sbom | Writes the package list as a CycloneDX or SPDX file. sbom --preview writes exactly what an upload sends, sends nothing, and needs no token. | The file that you name |
status | Reports the package managers that it found, the subscription, and the packages that have a TuxCare build. | Nothing |
init | Sets up a repository for TuxCare builds. See Set up a project. | Configuration files in the project |
registry login | Gives the package managers on this computer the credential of the TuxCare registry. | Configuration files in your home directory |
registry env --job-dir <dir> | Gives the package managers of one CI job the registry credential. See A CI job that installs TuxCare builds. | Files in the job directory only |
harden | Changes the project to TuxCare builds, installs them, and checks the result. See harden. | The manifest and the lockfile |
update | Moves each TuxCare build of the project to the newest build of the same version. See update. | The manifest and the lockfile |
check | The CI gate for a project that uses TuxCare builds. See check. | Nothing |
unharden | Removes the TuxCare builds and the settings that init and harden wrote. See unharden. | The manifest, the lockfile, and the configuration files |
migrate | Changes the old npm aliases npm:@els-js/… to the normal package names. | The manifest |
auth | Signs the CLI in and out. See Sign in the CLI. | The keychain |
doctor | Checks your environment: the package managers, the configuration, the proxy, and the connection to the portal. --bundle <path> writes a support archive, with the tokens removed. See Check your environment. | The archive that you name |
upgrade | Moves the CLI to the newest release. See Upgrade the CLI. | The CLI |
version | Prints the version of the CLI. | Nothing |
securechain --helplists the commands.securechain sca --helplists the options of one command.- Each command runs in the current directory.
--dir pathselects another project root. harden,update,init, andunhardentake--dry-run: they print the change and write nothing.
sca and sbom read the lockfiles of these ecosystems: npm, pnpm, Yarn, Bun, Deno, pip, uv, Poetry, PDM, Pipenv, conda, Maven, Gradle, Go, Cargo, Composer, Bundler, NuGet, Paket, Julia, Mix, Pub, SwiftPM, CocoaPods, Stack, and Cabal. harden and check work for JavaScript and Python projects, and in part for Deno. Maven and Gradle need a BOM file from TuxCare. See TuxCare builds.
Options of sca and compare #
| Option | Command | What it does |
|---|---|---|
--fail-on <severity> | sca | Exits with code 1 when an open finding is at this severity or higher: critical, high, medium, or low. Without it, sca only reports. |
--base <branch> | compare | The branch to compare with, for example main. Required. The base branch needs a scan of its own. |
--fail-on-new | compare | Exits with code 1 when the scan has an open finding that the latest scan of the base branch does not have. |
--min-severity <severity> | sca | Hides the findings below this severity from the printed report. JSON and SARIF output still hold them. |
--group-by <key> | sca | Groups the printed findings by ecosystem (the default), package, or severity. |
--output <format> | both | The format of the result. sca: human (the default), json, markdown, or sarif. compare: human or json. check also writes junit. The JSON format is stable: use it in scripts. |
--baseline-portal | sca | Skips the findings that your team ignores in the portal. |
--wait <duration> | both | How long to wait for the portal to match the scan. The default is 2m for sca and 5m for compare. |
--release <name> | sca | Records the scan as a release with this name. An empty name stops the run with exit code 2. See Record a release. |
--product-release <name> | sca | Also adds the release to this product release. Needs --release. |
--force-release | sca | Replaces a release of the same name that another commit holds. Needs --release. |
--on-portal-error warn | sca, check | Changes exit code 4 (the portal did not answer) to 0 with a warning. |
--dir <path> | all | The project root. The default is the current directory. |
--ecosystem <name> | all | Uses only this package manager, for example npm. You can give the option more than one time. |
Exit codes #
Code 1 is the result of a gate. Each other code that is not 0 means that the run did not finish.
| Code | Meaning | What to do |
|---|---|---|
| 0 | The run finished, and no finding reached the level that fails the job. | Nothing. |
| 1 | A finding failed the gate: a finding at the --fail-on level, a new finding for compare --fail-on-new, a newer build for update --check-only, or a problem that check found. | Read the findings in the job log or in the portal. |
| 2 | The command cannot run as you wrote it: a wrong option, a configuration file that the CLI cannot read, no package manager that it knows, or a browser sign-in in a CI job. | Read the message. Check the options and the directory. |
| 3 | The token is missing, wrong, expired, or revoked, the workspace refused it, a limit stopped it, the --tenant pin does not match, or the workspace has no registry token. | See Common errors. |
| 4 | The portal did not answer in time, or its answer failed a check. A CLI that is too old also gets this code. | Run the job again. Upgrade the CLI if the message tells you to. |
| 5 | A tool on your side failed: the install command of your package manager, or a file that the CLI cannot write. | Read the output of the tool in the job log. |
| 6 | harden, update, or unharden changed the project, but the installed packages are not the planned ones. The CLI put your files back. | Read the message: it names the package. Contact TuxCare if the error stays. |
| 7 | An error in the CLI. The CLI prints the path of a report file. | Send the report to TuxCare. |
The file .securechain.yaml #
securechain init writes this file into the project root. Commit it. It holds no secret. The CLI refuses a key that it does not know, with exit code 2, so a typo does not go unseen.
| Key | Meaning |
|---|---|
registry | The address of the registry, for example your own mirror. Without the key, the CLI uses the registry that the portal names. |
tenant | The name of your workspace. With this key, each command stops when the token belongs to another workspace. |
ecosystems | The package managers to use, when you do not want the CLI to find them. The option --ecosystem does the same for one run. |
ignore | A list of paths to leave out, for example test fixtures that have lockfiles of their own. The CLI reads no dependency file under these paths and sends nothing from them. |
submit.remote_repo_url | The repository URL to file the scans under. Without it, the CLI reads the URL from the CI variables, else from the git remote origin. |
baseline.portal | true makes sca skip the findings that your team ignores in the portal, as --baseline-portal does. |
reinstall | The install command of the project, as a list, when it is not the default one. For example npm: ["npm", "install", "--legacy-peer-deps"]. |
unharden | The original lines that init, harden, and update changed. unharden reads them. The CLI writes this key: do not change it. |
Access tokens #
A token lets a program use your workspace: the CLI, a CI job, a script, or an AI assistant. Open Access tokens in the workspace menu, type a Name that tells where the token is used, select the rights, set an expiry, and select Mint token.
Copy it at once and keep it in a secret store. The portal keeps only a hash of the token. If you lose a token, revoke it and make a new one.

- The name of the token.
- The scope. Only an admin sees this list.
- The rights: a preset, or your own selection of channels and permissions.
- Mint token makes the token and shows it one time.
- A token starts with
tuxr_and the name of your workspace. - The table shows the last four characters, the rights, the creation date, the last use, and the expiry of each token. Select Revoke to stop a token at once. A revoked token cannot come back.
- The Last CLI column shows the CLI version of the newest scan that the token sent.
older than
marks an old CLI. Use it to find a CI job that needs an upgrade. - The Browser sessions table lists your sign-ins. Select Sign out on a row to end that session.
Rights #
The rights of a token are two lists:
- Channels: how the token connects.
CLI
is the securechain CLI.API
is the REST API.MCP
is the MCP server for AI assistants. - Permissions: what the token can do.
submit
sends scans.read
reads repositories, scans, and findings.write
changes things: triage, the default branch, and the settings.poll
is for scan workers only: do not give it to a CI token.
Select a preset, or select Custom and tick each channel and permission:
| Preset | Channels | Permissions | Use it for |
|---|---|---|---|
| CI token (one repository) | CLI | submit, read | The CI job of one repository. Only an admin sees this preset. It sets the scope to one repository and the expiry to 90 days from today. |
| CI upload | CLI | submit, read | A CI job, or your own computer: send scans and read the findings. |
| Upload only | CLI | submit | A job that sends scans and reads nothing. |
| Read only | API | read | A script or a dashboard that reads findings. |
| Read and write | API | read, write | A script that also triages findings or changes settings. |
| AI assistant | MCP | read | An AI assistant that reads findings. |
| AI assistant with triage | MCP | read, write | An AI assistant that can also triage findings. |
- A token never does more than the role of its user. A viewer can only read, so a token of a viewer cannot send scans. The page shows only the presets that your role can give.
- The CLI channel is always on. An admin must turn on the API and MCP channels for the workspace.
- You cannot change the rights of a token. Revoke it and make a new one.
Scope #
An admin selects a Scope. The scope limits what a token can see on every channel. Use the smallest scope that does the job:
| Scope | What the token can do | Use it for |
|---|---|---|
| a repository | Send scans to one repository and read that repository only. | The CI job of one repository. If the token leaks, only that repository is exposed. |
| a department | Send scans and read the repositories of one department. A scan of a new repository puts the repository in that department. | A CI server that builds many repositories of one team. |
| myself, or a user | Act as that user, with the role and the departments of the user. The token stops when the user is disabled. | Your own computer, scripts, and AI assistant. |
| account-wide | Act as an admin of the whole workspace. | Automation that manages the workspace. Keep these few. |
A member or a viewer makes tokens for their own user only, and does not see the Scope list. A repository or department token cannot read other repositories, and it cannot make, list, or revoke tokens.
Expiry #
Set a date in Expires, or leave the field empty for a token that does not expire. The token stops at the end of that day in the time zone of your browser.
- An expired token gets the same answer as a revoked token: 401
unknown or revoked token
. The table marks itexpired
. - You cannot change the expiry. To replace a token: make the new token, change the CI secret, run the pipeline, then revoke the old token.
- A token that expires cannot make a token that expires later, or a token with no expiry.
API and MCP #
Programs can use your workspace in two more ways:
- The REST API at
/api/v1, for scripts, dashboards, and other tools. - The MCP server at
/mcp, for AI assistants such as Claude Code and Cursor. MCP is the Model Context Protocol.
Both are off in a new workspace. Each one needs a switch that an admin turns on, and a token with that channel in its rights.
Turn the API or MCP on #
- As an admin, open Settings › API and MCP access.
- Select the switch of API access or MCP access. It changes from
Off
toOn
, and the page showsSaved
. - Copy the API base URL or the MCP URL from the same section.
- On the Access tokens page, make a token with a preset for that channel.

- The switches. Each one shows its state.
- The base URL of the REST API.
- The URL of the MCP server.
- When you turn a switch off, every token stops on that channel at once. The other channels continue to work.
- The CLI and the browser work with both switches off.
- If the section has no switch for a channel, the channel is not available for your workspace. Contact TuxCare.
The REST API #
The base URL is https://name.sc.tuxcare.cloud/api/v1. Send the token in the Authorization header. The API does not accept a token in the URL.
curl -fsS \
-H "Authorization: Bearer $SECURECHAIN_API_TOKEN" \
"https://name.sc.tuxcare.cloud/api/v1/repos?limit=20"
- A
GETrequest needs the read permission. Any other method needs the write permission. - The OpenAPI document at
/api/v1/openapi.jsonlists each route, its permission, and the role that it needs. It needs no token. - The role and the scope of the token apply, the same as in the browser. The rate limit of each token also applies.
- Useful routes: the exports (
/api/v1/export/findings), the compliance report (/api/v1/repos/{id}/report), and the VEX file of a release (/api/v1/releases/{id}/vex).
The MCP server #
The MCP URL is https://name.sc.tuxcare.cloud/mcp. Use a token with the AI assistant preset, or AI assistant with triage if the assistant may triage findings. Each person uses a token of their own user.
Claude Code:
claude mcp add --transport http securechain https://name.sc.tuxcare.cloud/mcp \
--header "Authorization: Bearer <token>"
Cursor: add the server to ~/.cursor/mcp.json, or to .cursor/mcp.json in your project:
{
"mcpServers": {
"securechain": {
"url": "https://name.sc.tuxcare.cloud/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Do not commit a file that holds a token. The server gives the assistant these tools:
| Tool | What it does | Permission |
|---|---|---|
whoami | Tells the workspace, the scope, and the rights of the token. | none |
list_repos | Lists the repositories with the finding counts of the default branch. | read |
get_repo | Shows one repository: the tracked branch, the recent branches, the newest scan of each slot, and the finding counts. | read |
list_findings | Lists the findings of a branch. Filters: minimum severity, known exploited, triage state. | read |
get_finding | Shows one finding, as the finding page does. | read |
get_advisory | Shows an advisory and its other names. | read |
diff_ref | Shows the new and the fixed findings of a branch against an earlier scan or another branch. | read |
fix_plan | Shows the fix plan of a branch, as the Fix plan tab does. | read |
get_base_advice | Shows the base image of an image scan, how many open findings come from the base, and the base upgrades that remove findings. | read |
list_releases, get_release | List the releases of a repository, and show one release. | read |
triage_finding | Sets the triage state of a finding. It also needs the member or admin role. The audit log shows your email, then via MCP. | write |
- A slot is one project path and one set of ecosystems. A branch of a monorepo can have many slots.
get_repolists the scan id of each slot, and the other tools take a scan id to select a slot. - A list tool returns 50 rows by default and 100 at most. The assistant asks for the next rows when it needs them.
- When a tool fails, for example because a finding is outside the scope of the token, the assistant gets one sentence that tells why.
When the portal refuses a request #
| Answer | Cause | What to do |
|---|---|---|
403 this token cannot use the api channel(or cli, mcp) | The token does not have that channel in its rights. | Make a token with a preset for that channel. |
403 API access is off for this workspace(or MCP) | The switch of the channel is off. | Ask an admin to turn it on. |
403 this token cannot read(or submit, write) | The token does not have the permission, or the role of its user does not have it. | Make a token with the permission. A viewer can only read. |
404 no such route | The path is wrong, or the channel is not available for your workspace. | Check the path in the OpenAPI document. Contact TuxCare if the channel is not available. |
An AI assistant shows a 401, 403, or 404 as a connection error.
Next: Administration