Skip to content

Bitbucket secure-coding lessons

RansomLeak can comment on a Bitbucket Cloud pull request with a link to a short secure-coding lesson when a scanner reports a weakness on it. It is free, needs no RansomLeak account and is not part of your RansomLeak organization’s settings. It works in any Bitbucket Cloud workspace that uses Bitbucket Pipelines.

There are two parts. The pipe is all most teams need. The RansomLeak app is an optional extra.

Pipe Pipe with the app
Reads A SARIF file from your scanner The same SARIF file
Cost Free Free
Lesson comment Needs a repository access token, otherwise report only Posted as RansomLeak, no token
Ticks a finished lesson On the next pipeline run Within seconds
Code Insights report Yes, never failing Yes, never failing
Needs a workspace admin No Yes, once

Add the pipe after the step that runs your scanner and writes SARIF. The step needs oidc: true, so RansomLeak can tell which workspace and repository the request comes from.

pipelines:
pull-requests:
'**':
- step:
name: Scan and learn
oidc: true
script:
# ... your scanner writes results.sarif ...
- pipe: docker://ghcr.io/ransomleak/secure-coding-pipe:1
variables:
SARIF: results.sarif
BITBUCKET_ACCESS_TOKEN: $RANSOMLEAK_BB_TOKEN # optional

The pipe works with CodeQL, Semgrep, Trivy, Gitleaks and other tools whose rules carry a CWE, a CVE or a GHSA, and with secrets scanners. SARIF accepts a path or a glob such as reports/**/*.sarif, up to 50 MB in total. It runs only in pull request pipelines. Other pipelines skip it.

You don’t sign up. The pipe signs in to RansomLeak with the step’s OIDC token. If your pipe container does not receive BITBUCKET_STEP_OIDC_TOKEN, pass it explicitly with OIDC_TOKEN: $BITBUCKET_STEP_OIDC_TOKEN.

When the scanner flags a type of issue we have a lesson for, the pipe writes a Code Insights report on the commit with the lesson links. With a token it also adds one comment to the pull request and updates that same comment on later runs. The comment lists up to five lessons, one for each distinct issue type, each taking 5-10 minutes.

The RansomLeak comment on a Bitbucket pull request, listing the SQL Injection lesson as a link

The comment reflects what your scanner reports, so run it on changed files or with a baseline for less noise. When a SARIF result has a baselineState, only new and updated results count.

To get the comment, give the pipe a repository access token:

  1. In the repository, open Repository settings, then Access tokens.
  2. Create a token with the Pull requests: Write and Repositories: Read permissions.
  3. In Repository settings, then Repository variables, add it as a secured variable named RANSOMLEAK_BB_TOKEN.

Without the token, the pipe still publishes the Code Insights report with the lesson counts and an Open lesson link for each lesson, and prints a note. The report appears on the pull request under Reports. Installing the app is the other way to get a comment, and needs no token.

When someone finishes a lesson, the tick appears on the next pipeline run for that pull request, for example the next push. Without the app, nothing is written to the pull request between runs.

The same comment after the lesson was finished, with the lesson ticked and the completion date shown

The pipe never fails your build. If RansomLeak can’t be reached, the token is missing a permission, or the SARIF file is missing or invalid, it prints a warning and carries on.

If SonarQube already analyses your pull requests, the pipe can read its security findings instead of a SARIF file. Set SONAR_HOST_URL and leave SARIF out. Use exactly one source: with both or neither, the pipe prints a warning and does nothing.

- step:
name: Scan and learn
oidc: true
script:
# run the SonarQube scan for the pull request first, in the same step
- pipe: docker://ghcr.io/ransomleak/secure-coding-pipe:1
variables:
SONAR_HOST_URL: https://sonarcloud.io
SONAR_ORGANIZATION: my-workspace
SONAR_PROJECT_KEY: my-workspace_my-repo
SONAR_TOKEN: $SONAR_READ_TOKEN
BITBUCKET_ACCESS_TOKEN: $RANSOMLEAK_BB_TOKEN # optional
Variable Notes
SONAR_HOST_URL Your SonarQube Server URL, or https://sonarcloud.io for SonarQube Cloud.
SONAR_PROJECT_KEY The Sonar project key.
SONAR_ORGANIZATION SonarQube Cloud only.
SONAR_TOKEN Needs Browse permission on the project. Store it as a secured variable. Optional for public SonarQube Cloud projects.
SONAR_INCLUDE_HOTSPOTS Default false. Set true to also use HIGH and MEDIUM security hotspots still to review.
SONAR_WAIT_TIMEOUT Seconds to wait for Sonar’s analysis of the pipeline’s commit. Default 300.
  • When the scan left a report-task.txt in the same step, the pipe waits for that analysis. Otherwise, on SonarQube Cloud it waits for an analysis of BITBUCKET_COMMIT, and on Server it reads the latest analysis.
  • It reads the open vulnerabilities and each rule’s CWE ids. Findings without a CWE get no lesson, except rules with only an OWASP tag for A06 and A10.
  • SonarQube Server needs Developer Edition or above. Community Build does not analyse pull requests, so use SARIF with another scanner there.
  • The Sonar token is sent only to your Sonar host, never to RansomLeak. Only the scanner name (SonarQube), CWE ids and OWASP categories go to RansomLeak.
  • The pipe never fails your build. If Sonar can’t be read, it prints a warning and carries on.

The app posts the lesson comment as RansomLeak, ticks lessons as soon as they are finished, and keeps the Code Insights report current. It needs no access token.

A workspace admin installs it once for the whole workspace, from the install link. It asks for read and write access to pull requests and repositories, and nothing else.

The app is live. Install the RansomLeak app for Bitbucket.

Once the app is installed, the pipe asks RansomLeak who should post. The app posts and the pipe only writes the report. If the pipe already posted a comment on that pull request, the app starts its own comment with every lesson and tick carried over, and the pipe’s earlier comment is replaced by a one-line pointer to it. One lesson comment stays active.

If the app is removed from the workspace, the next pipe run posts the comment again with the token, and finished lessons stay ticked. To stop using the app, uninstall it from the workspace settings.

Pull requests from forks get the Code Insights report only. No comment is posted, with or without the app.

  • SQL injection
  • Cross-site scripting (XSS)
  • Path traversal
  • Command injection
  • Server-side request forgery (SSRF)
  • Hard-coded secrets
  • XML external entities (XXE)
  • Open redirect
  • Cross-site request forgery (CSRF)
  • Vulnerable dependencies

Deserialization and weak cryptography have no lesson yet.

A finding matches on its CWE. Findings from secrets scanners and dependency advisories match on the scanner type. OWASP categories and broad parent CWEs such as CWE-200 are not used, because they don’t point to one specific lesson.

Fixing the code does not remove the lesson from the comment.

The pipe sends only identifiers: the scanner name, the CWE ids of the rules that produced a result, whether a rule is a CVE or GHSA advisory, the pull request number and the commit hash. The workspace, repository and step identifiers come from the signed OIDC token. No source code, file names, line numbers, messages, snippets or secrets leave the runner.

RansomLeak keeps no per-developer record. It stores:

  • With the app installed, one install record per workspace: the install id, the workspace UUID, the app’s web trigger URL and a relay secret that we generate and store encrypted. No personal data. Uninstalling the app deletes it.
  • For each finished lesson, one completion mark per workspace, repository, pull request and lesson, holding only ids and the time of the first completion. It expires after 30 days.

We store no names, emails or Bitbucket credentials. Your access token stays in your pipeline and is sent only to Bitbucket. See the privacy policy.

The lesson link belongs to the pull request, not to a person. Anyone who can open the pull request can open the link and mark the lesson finished.

A tick means the lesson was completed via that link. Use it as a nudge, not as proof of who did the training.

What you see What to check
Warning about a missing OIDC token The step needs oidc: true. If it is set, pass OIDC_TOKEN: $BITBUCKET_STEP_OIDC_TOKEN to the pipe.
No comment, only a report No BITBUCKET_ACCESS_TOKEN was set and the app is not installed, or the pull request is from a fork.
Warning about 401 or 403 from Bitbucket The token lacks Pull requests: Write or Repositories: Read, or it has expired. The warning names the permission.
Warning about 429 Bitbucket rate-limited the request. The comment is skipped this run and returns on the next one.
The pipe says it is skipping It runs only in pull request pipelines. Put it under pipelines: pull-requests:.
Warning about the SARIF file The path matches nothing, the file is empty or invalid, or it is over 50 MB.
No lessons at all None of the findings maps to a lesson. Check that your scanner’s rules carry a CWE, CVE or GHSA.
No report The pipe could not reach the Pipelines proxy that writes Code Insights reports. Check the step log for the warning.
  • Lessons are in English.
  • Bitbucket Cloud only. Bitbucket Data Center is not supported.
  • The report and comment are written on the pull request’s source commit.
  • A lesson shows only when a scanner’s finding maps to one. Findings with no matching lesson get no comment, including findings with only an OWASP category.