Fix vulnerabilities
How to close the findings of a project: with an upgrade to a fixed version, or with a TuxCare build of the version that you use now. The CLI makes the change, checks it, and keeps it current.
Two ways to fix #
| Upgrade the package | Use a TuxCare build | |
|---|---|---|
| What changes | The version: you move to the lowest version that fixes the advisory. | The source: the same version, built by TuxCare from source with the fix added. Its version ends in -tuxcare.N (Python: +tuxcare.N). |
| Use it when | The fixed version is close, and its changes do not break your code. | The fix is in a new major version, or the project that made the package no longer fixes your version. |
| How | Your package manager, for example npm install lodash@4.17.21. | securechain harden. See TuxCare builds. |
| Needs | Nothing more. | A subscription with TuxCare builds. |
The portal tells you which fix applies:
- The Fix plan tab of a repository lists each package to change, the version to move to, and where the fix comes from:
upstream
or a TuxCare build. - The page of a finding shows How to fix: the recommended fix, the alternatives, and the command to run.
- The TuxCare coverage tab of Packages counts the packages of the workspace that a TuxCare build can fix.
Upgrade a package #
- Open the Fix plan tab of the repository. A package with a known-exploited finding comes first.
- Change the version of the package with your package manager. For a transitive package, upgrade the direct dependency that pulls it in, or add an override.
- Run your tests, and commit the manifest and the lockfile.
- Run
securechain sca, or let the CI job run it. The finding closes when the portal gets a scan that does not have it.
The fix plan marks an upgrade to a new major version with major version
. Such an upgrade can break your code. A TuxCare build avoids it.
TuxCare builds #
TuxCare builds the open-source packages that your projects use from their source, and serves the builds from the TuxCare registry. When a vulnerability is found in a version, TuxCare adds the fix to that version and publishes a new build. TuxCare also fixes versions that the project that made them no longer maintains. A new upstream version reaches the registry only after TuxCare checks it, for example for malicious code.
The CLI moves a project to the builds in three steps: init one time for each repository, registry login one time for each computer, and harden each time you want to apply the builds.
What you need #
- A subscription with TuxCare builds.
securechain auth statusshows it in the lineentitlement.securechain=false els=falsemeans that your workspace has none. Contact TuxCare. - A registry token in the workspace. An admin saves it one time under Settings › Registry token.
- A committed lockfile, for example
package-lock.json. - A supported package manager: npm, pnpm, Yarn, Bun, pip, uv, Poetry, PDM, Pipenv, or conda. Deno: the
importsofdeno.jsononly. Maven and Gradle need a BOM file from TuxCare (--bom-file).
Set up a project #
cd path/to/your/project
securechain init # one time for each repository
securechain registry login # one time for each computer
initwrites.securechain.yamland makes the TuxCare registry the package source of the project, for example in.npmrc. It writes no credential. Commit the files that it names.init --dry-runshows the changes and writes nothing.registry logingets the registry credential from your workspace and writes it into the configuration of your package managers in your home directory, for example~/.npmrc. Each person who installs the project runs it one time. Run it again when an admin changes the registry token.- If the project already uses your own registry, such as Artifactory or Nexus,
initandregistry loginkeep it and tell you so.--replace-sourcemakes the TuxCare registry the source.
Move the project to the builds: harden #
securechain harden --dry-run # show the plan and the changes; write nothing
securechain harden
hardenasks the portal which TuxCare builds your subscription has for the dependencies of the project.- It writes those builds into the manifest and the lockfile.
- It runs the install command of your package manager.
- It checks that each planned build is installed. If the check fails, it puts your files back and exits with code 6.
- It sends the new package list to your workspace.
Then run your tests, and commit the manifest and the lockfile.
hardenkeeps the version of each package.1.3.1moves to the newest build of1.3.1, for example1.3.1-tuxcare.2.--allow-minor-upgradeslets a package move to a later version with the same major and minor numbers, when only that version has a build that closes the findings.1.3.1can move to1.3.2-tuxcare.1, never to1.4.0.--includeand--excludelimit the run to the packages that you name.
Keep the builds current: update #
securechain update --check-only # exit code 1 when a newer build exists; write nothing
securechain update
TuxCare publishes a new build when it fixes a new vulnerability in a version. update moves each TuxCare build of the project to the newest build of the same version, for example from 1.3.1-tuxcare.2 to 1.3.1-tuxcare.3. It installs and checks the result, as harden does. Run it on a schedule, or when the portal shows a finding that a newer build fixes.
The gate: check #
securechain check reads the installed dependencies and changes nothing. It exits with code 1 when the project is not in the state that harden made:
- A package has a finding, your subscription has a TuxCare build that fixes it, and the project does not use the build.
- A newer TuxCare build exists for a build that the project uses.
- The lockfile points at the public registry for a package that
hardenmoved to a TuxCare build.
--explain prints the evidence and the fix for each problem.
TuxCare builds in CI #
A job that installs TuxCare builds needs the registry credential before the install step. The job does three things in this order: get the credential, install, run check.
GitHub Actions:
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: TuxCare/securechain-action@v0
with:
command: registry
portal-token: ${{ secrets.SECURECHAIN_PORTAL_TOKEN }}
- run: npm ci
- uses: TuxCare/securechain-action@v0
if: always()
with:
portal-token: ${{ secrets.SECURECHAIN_PORTAL_TOKEN }}
registry-login: none
- The first use of the action gets the credential for the install step.
- The second use runs
securechain checkand sends its result to GitHub code scanning.if: always()runs it after a failed install too: its last step removes the credential of the job.
GitLab CI:
securechain:
image: node:22 # any image that has curl and your package manager
script:
- curl -fsSL https://securechain.tuxcare.com/get/securechain | sh
- out="$(securechain registry env --job-dir "/tmp/securechain-job-$CI_JOB_ID" --format shell)"; eval "$out"
- env -u SECURECHAIN_PORTAL_TOKEN npm ci
- securechain check --output junit > report.xml
after_script:
- rm -rf "/tmp/securechain-job-$CI_JOB_ID"
artifacts:
reports:
junit: report.xml
registry env --job-dirwrites the credential into a directory for this job, and prints the variables that point npm, pnpm, Yarn 1, and the Python tools at it. It changes no file in the home directory of the runner.env -u SECURECHAIN_PORTAL_TOKENruns the install without the access token, so the install scripts of your dependencies cannot read it.- On gitlab.com, the CI/CD component does these steps for you, also for Yarn 2 and later and for Bun:
include:
- component: $CI_SERVER_FQDN/tuxcare/securechain-ci/check@0
inputs:
stage: test
install: npm ci
Rules for a project with TuxCare builds #
- Commit the lockfile, and install from it. In CI, use the install command that follows the lockfile, for example
npm ci. - Move TuxCare builds with
securechain updateonly. A version that ends in-tuxcare.Nis not in the public registry.npm update,npm audit fix, and other tools that select versions by themselves do not know these builds. They stop withETARGET, or they put the public version back. - Add a new dependency as usual, for example with
npm install name. Then runsecurechain hardenagain, so that the new packages get their builds.
Renovate and Dependabot #
An update bot does not know TuxCare builds. Without a rule, it opens a pull request that replaces 1.4.5-tuxcare.1 with the public 1.4.6.
- Renovate:
securechain initwrites a rule intorenovate.json. Renovate then proposes only the next TuxCare build for a package that is on a TuxCare build. - Dependabot:
securechain initwrites the TuxCare registry and anignorelist into.github/dependabot.yml, andhardenkeeps the list current. Add the registry token as the Dependabot secretTUXCARE_TOKENin the settings of the repository.
npm: the two paths of the registry #
For npm, the TuxCare registry has two paths on one host:
/npm-upstream/serves the packages of the public npm registry, byte for byte.initandregistry loginwrite it as the registry of the project and of your computer./npm/serves the TuxCare builds.hardenandupdatewrite it into the lockfile lines of the builds, with the hash of each build.
So a new TuxCare build never changes what an existing lockfile installs, and the install does not fail with EINTEGRITY. pnpm and Yarn 2 or later keep no package address in the lockfile: for them, the CLI writes /npm/ as the source.
Remove TuxCare builds: unharden #
securechain unharden --dry-run # show the changes; write nothing
securechain unharden
unharden undoes init and harden. Use it when you stop the subscription, or to go back to the public packages.
- It puts back each line that
init,harden, andupdatechanged. These commands keep the original text underunharden:in.securechain.yaml. For a line with no record,unhardenwrites the base version of the build:4.4.3for4.4.3-tuxcare.5. - It removes the registry lines, the overrides, and the bot rules that the CLI added, and
.securechain.yaml. - It installs again from the public registry and checks that no TuxCare build is left. If the check fails, it puts your files back and exits with code 6.
- It needs no token, so it works after the subscription ends.
Then run your tests, and commit the changed files.
Next: Reference