Skip to content

Azure DevOps secure-coding lessons

RansomLeak can comment on an Azure Repos 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 Azure DevOps Services organization.

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

Pipeline task Pipeline task with the app
Reads A SARIF file from your scanner The same SARIF file
Cost Free Free, plus one Basic seat in Azure DevOps
Ticks a finished lesson On the next pipeline run Straight away
Pull request status No Yes, never failing
Needs a directory admin No Yes, once

Install RansomLeak Secure Coding Lessons from the Visual Studio Marketplace into your organization. Then add the task after the step that runs your scanner and writes SARIF.

steps:
# ... your scanner writes results.sarif ...
- task: RansomLeakLessons@1
condition: always()
inputs:
sarif: results.sarif

The task works with CodeQL, Semgrep, Trivy, Gitleaks and other tools whose rules carry a CWE, a CVE or a GHSA, and with secrets scanners. It runs only on pull request builds of Azure Repos Git repositories, so add the pipeline as a build validation policy on the target branch. Other builds skip it.

You don’t sign up or add a secret. The task signs in to RansomLeak with the pipeline’s own identity token, which proves which organization, project and repository it runs in. No service connection is needed.

When the scanner flags a type of issue we have a lesson for, the task adds one comment thread to the pull request and updates that same thread on later runs. It lists up to five lessons, one for each distinct issue type, each taking 5-10 minutes.

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.

The pipeline’s identity needs permission to comment. Do this once per repository, or once for all repositories:

  1. Open Project settings, then Repositories.
  2. Select the repository, or All Repositories, and open Security.
  3. Select the {Project} Build Service ({Organization}) user.
  4. Set Contribute to pull requests to Allow.

Repository Security in Azure DevOps with Contribute to pull requests set to Allow for the project Build Service

If the permission is missing, the task prints these steps as a warning and posts nothing.

When someone finishes a lesson, the tick appears in the thread 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 task never fails your build. If RansomLeak can’t be reached, the permission is missing, or the SARIF file is missing or invalid, it logs a warning and carries on. Pull requests from forks are skipped.

The RansomLeak lesson thread on a pull request, with two lessons ticked as completed and one still open

The app ticks lessons as soon as they are finished and sets a pull request status. It needs three things in your organization:

  • Approval by a directory admin. A Microsoft Entra Global Administrator, Cloud Application Administrator or Application Administrator approves the app for your tenant.
  • Basic access. Add the app to the Azure DevOps organization as a user with Basic access, and to the project with the repository. Stakeholder access can’t see repositories. Every organization has 5 free Basic users: if one is spare, the seat costs nothing, otherwise it is a paid Basic seat you buy from Microsoft.
  • Contribute to pull requests. Grant it to the app the same way as for the Build Service above, choosing RansomLeak Secure Coding instead.

To connect, open app.ransomleak.com/azure-devops/connect and choose Sign in with Microsoft. After approving, fill in your organization, project and repository and choose Check access. The page tells you exactly what is missing.

The RansomLeak Connect page after a successful access check, listing the three checks that passed

Once connected, the task’s lessons are posted under the app’s name and a finished lesson is ticked straight away. The app also sets a pull request status named ransomleak/secure-coding. It is pending while lessons are open and succeeded when all listed lessons are finished. It never fails.

The app only edits threads it started itself. On a pull request where the task already posted a thread before you connected the app, the app starts its own thread with every lesson and tick carried over, and closes the task’s thread so one lesson thread stays active. It works the other way too: if the app is disconnected, the next task run updates its own thread and closes the app’s.

Don’t make this status a required policy: pull requests without lessons never report it.

If the app loses its access, for example it is removed from the organization, it is marked disconnected and the task takes over again. Running Check access again reconnects it. To stop using the app, choose Disconnect on the Connect page and remove it from the organization’s users.

Organizations not backed by Microsoft Entra ID can use only the task.

  • 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 thread.

The task 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, and the pull request number. The organization, project and repository come from the pipeline’s identity token. No source code, file paths, messages, snippets or secrets leave the agent.

Each lesson link holds a token with the organization and project names and ids, the repository id, the pull request number, the lesson and internal ids. A finished lesson needs them to reach the right pull request. The token is signed, not encrypted, so anyone with the link can decode it and read those values.

RansomLeak keeps no per-developer record. It stores:

  • Up to two install records per organization: one for the task and, if you connect it, one for the app. Each holds ids plus a signing key and an ingest secret that we generate and store encrypted. The app’s record also holds the organization name, your Microsoft Entra tenant id and when it was connected. No personal data. Support removes them on request.
  • For each finished lesson, one completion mark per organization, repository, pull request and lesson, holding only ids and the time. It expires after 30 days.

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.

  • Lessons are in English.
  • Azure DevOps Services only. Azure DevOps Server is not supported.
  • Alerts from GitHub Advanced Security for Azure DevOps don’t produce lessons on their own, because alerts found on pull request branches aren’t stored. Export your scan results as SARIF and pass the file to the task.
  • Pull requests from forks are not supported.
  • 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.