For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /tutorials/vulnerability-remediation.md.

Set up Vulnerability Remediation

Info

Takeaways

  • Vulnerability Remediation is a second capability of the Tessl Reviewer GitHub App. It scans a pull request for the vulnerabilities that pull request introduced, fixes the ones the scanner reports a fix for, and verifies each fix with a rescan.
  • Turn it on per repository, choose Snyk or Semgrep and Dependabot as the scanner, and choose whether Tessl pushes a fix commit or posts the fix as review suggestions.
  • Ask for a run with @tessl-remediation on the pull request. Read the result in the status comment and the Tessl Vulnerability Remediation check.
Warning

Vulnerability Remediation is in early access. If your organization doesn't have it yet, contact us for early access. Once it does, the Reviewer page shows a Vulnerability Remediation tab.

Agents open pull requests faster than a security team can read them, and a scanner that only reports findings leaves the fixing to a person. Vulnerability Remediation closes that gap on each pull request: it scans the change, attempts a fix for every finding it is able to fix, rescans to verify each fix, and reports on the pull request. Nothing is pushed unless a rescan no longer reports the finding.

Runs use Tessl's infrastructure and the same GitHub App as Code Review. Each run uses tokens minted for that run and scoped to the single repository.

Before you start

Vulnerability Remediation needs the Tessl Reviewer GitHub App installed and the repository reachable by it. If you have already set up Code Review, both are done. If not, follow Step 1 of Set up Tessl Code Review, then come back here. Installing the App does not start anything: you also turn Vulnerability Remediation on per repository, below.

Each capability of the App is turned on separately. A repository with Code Review on and Vulnerability Remediation off gets reviews and no remediation, and the other way around. You don't need Code Review on to use Vulnerability Remediation.

Step 1: Connect Snyk

Snyk is the default scanner, and it scans with your own Snyk account. Skip this step if the repository will use Semgrep or Dependabot, which need no connection.

  1. Sign in to tessl.io, select your organization, and open Reviewer in the sidebar, then the Vulnerability Remediation tab.
  2. Select Connect Snyk.
  3. Enter a Snyk API token and the ID of the Snyk organization to scan under, then save.

The connection is organization-wide: every repository that scans with Snyk uses it. Connecting needs the organization's manage-integrations permission, so a repository admin without it sees Ask an organization manager to connect Snyk.

Tessl checks the token against Snyk before saving it. A rejected token or an organization the token can't reach is reported and nothing is saved. The token is stored encrypted, is never shown again, and is used only while a run scans. It never appears in a log, a result, or a fix. To rotate it, select Replace and enter the new one.

Step 2: Turn it on for a repository

  1. On the Vulnerability Remediation tab, select the repository.
  2. Switch on Turn on for this repository.
  3. Choose the Mode and the Scanners, described below, and save.

Changing a repository's settings needs the organization's manage-integrations permission.

A repository the App can reach but that you haven't turned on is never scanned, however many times someone comments. If its settings have never been saved, a comment gets no reply. If it was turned on and then off, a comment gets a reply saying it isn't enabled.

Choose the mode

Mode decides what a run does with a verified fix.

  • Fix. Tessl pushes one fix commit to the pull request branch, then asks Code Review to review that commit. This is the default.
  • Advisory. Tessl posts each fix as a review suggestion you apply yourself, and never pushes. A fix GitHub can't show as a suggestion, such as a regenerated lockfile, is carried in the review body instead.

In either mode a fix is only published once a rescan no longer reports the finding it fixes.

Choose the scanners

ScannerScansNeeds
SnykCode, open source dependencies, infrastructure as code, and containers. Choose which of the four under Scan modes; code and dependencies are on by default.The organization's Snyk connection.
SemgrepChanged code, with Semgrep's default ruleset.Nothing.
DependabotChanged lockfiles, looked up in the GitHub Advisory Database. This is a lookup Tessl runs, not the Dependabot service.Nothing.

Snyk runs on its own. Semgrep and Dependabot scan different things, so you can run either or both; when both are on, Semgrep finishes before Dependabot starts, and one run works through both scanners' findings.

Every scanner reports only what the pull request introduced. A code or infrastructure finding has to land on a changed line, a dependency finding has to belong to a dependency the pull request added or changed, and a container finding has to come from a changed Dockerfile that selects a new base image. Vulnerabilities already on the base branch aren't reported.

A changed file the scanner didn't examine is listed in the result under Not scanned, with the reason, rather than treated as clean. Dependency scanning needs a lockfile the scanner can read without installing the project: npm, pnpm, Yarn, Bun, uv, and Poetry lockfiles are scanned, and other ecosystems are listed as not scanned.

Snyk test allowance

Snyk doesn't charge per scan, but each scan a run makes counts as a test against your Snyk plan's monthly allowance, in the same way a snyk test from a terminal does. Snyk counts one test per lockfile or base image a scan examines, so a run uses tests before it starts and again on each rescan after a fix attempt. A run that fixes several findings uses several tests. Snyk's own definition of a test is in What counts as a test. The Semgrep and Dependabot scanners have no allowance.

Ask for a run by comment

Comment on the pull request, on the Conversation tab or inline on the diff. The comment has to contain @tessl-remediation as plain text, not quoted or in backticks.

  • @tessl-remediation starts a run: scan, fix, rescan, publish.
  • @tessl-remediation scan scans and fixes nothing. The result lists the findings a run would attempt under Fixable, so you can see what a run would change before asking for it, or confirm a head after applying advisory suggestions. A scan doesn't count toward the limits below.
  • @tessl-remediation undo reverts the fix commit of the latest run that pushed one, as a new commit, without force-pushing. If a later commit changed a file the fix touched, the reply gives the git revert command to run by hand instead.

Anyone with write access to the repository can ask. A comment from anyone else gets a reply saying so. Automated agents can be allowed too; ask us to add their logins to the repository's trusted requesters. A trusted requester can start runs and scans, but only someone with write access can undo.

Two check actions also start runs. Re-run on the Tessl Vulnerability Remediation check runs the same kind of run again, scan or fix, on the current head. Re-run all checks does the same, but only on a pull request where remediation has already run, so turning the capability on doesn't add a run to every re-run of Code Review.

Each run gets its own status comment, edited in place as the run goes, and one check on the head it ran on. One run at a time: a second comment while a run is queued or running gets a reply saying so and starts nothing.

What a run fixes

A run attempts every finding the scanner reports a fix for and leaves the rest for a person:

  • A dependency or container finding is attempted when the scanner names a fixed version, or a base image, that clears it.
  • A code or infrastructure finding is attempted when the scanner gives a fix hint.
  • Everything else is listed under No automatic fix, with the scanner's guidance where it gave any.

A few findings with a scanner fix are still left for you, under No automatic fix: an upgrade that crosses a major version (or a minor version below 1.0), since its breaking changes need a decision, and a fix that needs a new dependency added. The result says which rule applied.

For a code finding it can edit the flagged file. For a Snyk code finding it can also edit any other file the pull request changed along the vulnerable data flow; a Semgrep fix stays in the flagged file. For a dependency finding it can edit that project's manifest, and the lockfile is regenerated. A fix that would belong in a file the pull request didn't touch, or that needs a new file or dependency, isn't made; the finding is listed under Could not fix with the reason.

Each attempt is rescanned; one the rescan doesn't verify is rolled back, and the next attempt starts from the original code with that outcome as context. After the last attempt a finding that is still reported keeps its original code and is listed under Could not fix, with the reason: the attempts ran out, the agent judged it a false positive and says where the value becomes safe, the change strayed outside the finding, the lockfile couldn't be regenerated, or the rescan didn't complete.

What gets published

A completed run publishes:

  • A status comment that opens with a one-sentence headline, lists every finding under exactly one heading, and ends with a count line, such as 1 fix, 2 remaining, 1 ignored, 3 iterations. The headings are Fixed, No automatic fix, Could not fix, Ignored (a Snyk Code finding the connected Snyk organization has an accepted, unexpired ignore for, shown with its reason), Not scanned, and Warnings (files the scanner couldn't fully parse). Line numbers refer to the pull request head before any fix commit.
  • A fix commit on the branch in Fix mode, or a review with suggestions in Advisory mode. Fixes that verified are published whatever else the run found.
  • A check run, Tessl Vulnerability Remediation, on the fix commit when the run pushed one, and otherwise on the head it scanned:
CheckMeaning
SuccessEvery finding was fixed and verified, and every scan completed. In Advisory mode, a verified fix counts as fixed once it is posted as a suggestion. For a scan, nothing was found and every scan completed.
NeutralThe run finished, and something is left for a person: a finding under No automatic fix or Could not fix, a scan type that didn't complete, or the run reached its time limit. An undone run is also neutral.
FailureThe scanner refused the connected account, the run failed before it produced a result, the run stopped after an unexpected error, or the fix couldn't be published, for example because the branch moved.

A clean result names the scanner and says it found no vulnerabilities in the changes it scanned. A scanner reports what its rules match; it's not a security review.

The check holds a merge only when your branch protection or ruleset requires it. Leave that off and every result stays informational.

Limits

  • Attempts. Each finding gets up to 10 fix attempts by default. Change it, from 1 to 100, with the repository's Maximum iterations.
  • Runs per pull request. The repository's Maximum rounds setting (default 3) caps how many fix runs a pull request can have in total, so remediation and review can't keep changing the same code back and forth. A request past it gets a reply saying so.
  • Runs per hour. At most six fix runs per pull request per hour.
  • Time. A run stops starting new attempts after 50 minutes and ends with the fixes it has. A run that hasn't finished 90 minutes after it was requested is reported as failed.
  • Moved head. A run only publishes onto the head it scanned. If the branch moved while a run or a scan was going, nothing is published, the check fails with that reason, and the status comment shows only that failure, with no findings. Comment again to run on the new head.

Scans count toward none of the run limits.

Permissions the App holds

Vulnerability Remediation uses the permissions the App already requests for Code Review, listed in Set up Tessl Code Review. Turning it on doesn't ask for new permissions. Each run uses tokens minted for that run and scoped to the single repository.

Troubleshooting

SymptomWhat to check
A comment did nothing, and there's no replyThe repository's Vulnerability Remediation settings have never been saved, or your organization doesn't have access yet. Turn it on in the Tessl web app, or check the tab for the early-access notice.
"Vulnerability remediation did not start: Vulnerability remediation is not enabled for this repository."It was turned off. Turn it on in the repository's settings on the Vulnerability Remediation tab.
"Vulnerability remediation did not start: Connect Snyk before requesting Snyk remediation."The repository scans with Snyk and the organization has no Snyk connection. Connect one, or switch the repository to Semgrep or Dependabot.
"Vulnerability remediation did not start: Vulnerability remediation requires repository write access."Only someone with write access can start a run. For an automated commenter, ask us to add it to the repository's trusted requesters.
"Vulnerability remediation did not start: ...requires an open, non-draft pull request whose branch belongs to this repository."Draft pull requests and pull requests from forks aren't scanned. Mark the pull request ready, or push the branch to the repository.
"Vulnerability remediation did not start: ...has reached this repository's limit of N runs per pull request."Raise Maximum rounds in the repository's settings, or open a new pull request.
"Vulnerability remediation did not start: ...is limited to six runs per pull request per hour."Wait, then comment again.
"A vulnerability remediation run is already in progress on this pull request"Wait for the status comment to settle, then comment again if you need another run.
The check is neutral on a clean-looking resultOpen the status comment. Something is left for a person: a finding under No automatic fix or Could not fix, or a scan type that didn't complete, for example a dependency file the scanner can't read.
The run failed before reporting any findingThe scanner couldn't run at all: the Snyk token was rejected or revoked, or the scanner crashed on its first scan. Check the Snyk connection, then comment again.
A fix was pushed that you don't wantComment @tessl-remediation undo.