Cerbi Scanner - Azure DevOps ExtensionRun Cerbi's local scanner in Azure DevOps to catch risky, sensitive, and costly logging patterns before production, including metadata-only AI integration signals from supported scanner versions. The extension is intentionally a Marketplace/pipeline wrapper: it installs or resolves the
Marketplace package metadataThis extension publishes as Current package version: Marketplace links are intentionally pointed at Cerbi-owned resources for scanner onboarding, support, and privacy information. The source repository remains linked for task implementation review and issue traceability. Scanner contractCerbi findings are expected to use stable rule IDs and include automation-friendly metadata: rule ID, title, message, severity, file path, line, column when available, excerpt when available, recommendation, confidence, and detected field or pattern category when available.
Scanner Policy-as-codeThe scanner should discover policy files named:
You can also pass an explicit policy path with the task Local scanner installation (.NET 10 LTS)Cerbi Scanner is distributed as the
For reproducible enterprise builds, pin .NET 10 LTS upgrade notes
Data handling and network behaviorThe Azure DevOps task runs the scanner on the build agent and does not upload source code, logs, findings, or report files to a Cerbi service. By default, outputs are written to the pipeline artifact staging directory and can be attached to the Azure DevOps build summary/artifacts when The task may make two outbound network calls only when configured to install prerequisites: Pipeline usageInstall .NET 10 explicitly with Demo/report mode (
|
| Input | Default | Description |
|---|---|---|
scanPath |
$(Build.SourcesDirectory) |
Solution, project, folder, or file path passed to cerbi-scanner scan --path. |
policyPath |
empty | Optional policy path passed to --policy. If omitted, scanner discovery/default behavior applies. |
failOn |
none |
error | blocker | warning | info | low | medium | high | critical | none. |
failOnNew |
none |
Legacy compatibility input only. Values other than none are rejected because the current scanner has no baseline/new-finding mode. |
ci |
true |
Deprecated compatibility no-op. Accepted for existing YAML/default task usage, but no --ci flag is emitted because current report outputs and --fail-on behavior are CI-compatible. |
reports |
markdown,json,sarif |
Comma-separated report formats mapped to supported scanner outputs: --summary, --format json --output, and --sarif. |
outputDir |
$(Build.ArtifactStagingDirectory) |
Compatibility input used only to derive jsonOutput, sarifOutput, and markdownSummary defaults. It is not passed as --output-dir. |
baseline |
empty | Unsupported with the current scanner. Non-empty values are rejected. |
createBaseline |
empty | Unsupported with the current scanner. Non-empty values are rejected. |
verbose |
false |
Legacy compatibility input only. true is rejected because the confirmed scanner contract used by this task has no --verbose. |
jsonOutput |
$(Build.ArtifactStagingDirectory)/cerbi-results.json |
JSON report path passed to --format json --output. |
sarifOutput |
$(Build.ArtifactStagingDirectory)/cerbi-results.sarif |
SARIF report path passed to --sarif. |
markdownSummary |
$(Build.ArtifactStagingDirectory)/cerbi-report.md |
Markdown report path passed to --summary and published to the build summary when generated. |
includeSnippets |
false |
true passes --snippets; false passes --no-snippets. Keep false for safer shared CI artifacts. |
publishArtifacts |
true |
Publish generated JSON and SARIF reports as build artifacts. |
uploadToCerbiShield |
false |
Explicitly disabled by default. This wrapper keeps scans local and does not upload findings. |
scannerVersion |
latest |
NuGet version of Cerbi.Scanner to install. Pin 1.2.0 or later in regulated pipelines that want AI integration detection. |
installScanner |
true |
Install/update the scanner before running. Disable for self-hosted agents with a preinstalled, approved scanner. |
scannerInstallDirectory |
$(Agent.ToolsDirectory)/cerbi-scanner |
Tool-path install directory used before PATH/global-tool probing. |
packageSource |
empty | Optional NuGet feed URL or local source for private feeds or mirrored packages. |
installDotNet |
true |
Install the .NET 10 SDK with the official dotnet-install script when the agent does not already provide .NET 10. |
dotNetVersion |
10.0.x |
.NET SDK version/channel used by the fallback installer. |
dotNetInstallDirectory |
$(Agent.ToolsDirectory)/dotnet10 |
SDK install directory used by the fallback installer and prepended for the current task. |
additionalArguments |
empty | Supplemental scanner arguments such as --exclude, --config, --app, --repo, --branch, --commit, and --build-id. Task-managed options are rejected here. |
Legacy inputs (policyFile, failThreshold, outputFile, sarifOutputFile, markdownSummaryFile, and failOnSeverity) are still read as aliases where practical, but new pipelines should use the scanner-first inputs above.
CLI behavior invoked by the task
The wrapper verifies that the installed scanner supports scan. If cerbi-scanner scan --help is unavailable, the task fails clearly instead of silently falling back to legacy audit behavior:
Cerbi Scanner version X does not support the scan command. Upgrade to Cerbi.Scanner >= 1.1.0.
The wrapper then runs one scanner-first command:
cerbi-scanner scan --path <scanPath> --policy <policyPath> --fail-on <failOn> --format json --output <jsonOutput> --sarif <sarifOutput> --summary <markdownSummary> --no-snippets
--policy is omitted when policyPath is empty; --profile is included only when profilePath is set. --policy and --profile are mutually exclusive because the scanner does not allow the scanner-first YAML/JSON configuration path and the legacy governance-profile path together. Baseline/new-finding inputs and verbose: true are rejected because the current scanner contract used by this task does not expose --baseline, --create-baseline, --fail-on-new, or --verbose. ci is accepted as a deprecated no-op and never emits --ci. outputDir is translated into explicit report file paths and is never passed as --output-dir.
Exit codes are interpreted as:
| Code | Meaning |
|---|---|
0 |
Scan complete, no findings meet the fail threshold |
1 |
Findings found at or above the configured threshold |
2 |
Scanner/configuration error |
Implementation plan for scanner changes
Smallest safe plan for the scanner repository:
- Keep detection in the local
Cerbi.ScannerCLI and expose one shared finding contract for console, JSON, SARIF, markdown, and Azure DevOps. - Add policy loading for the three supported names plus
--policy, with safe defaults when absent. - Normalize severities to
warning,error, andblocker; apply rule enablement and overrides before output/fail decisions. - Implement or verify
CERBI001-CERBI006in the existing supported analyzer path only. If only .NET/Roslyn is currently implemented, document that clearly and keep future language scanners behind the same contract. - Add focused fixtures and tests for each rule, policy overrides, fail threshold, JSON, SARIF, markdown, and this Azure DevOps wrapper argument/report-publishing mapping.
Unsupported legacy baseline inputs
The current Cerbi.Scanner CLI does not implement baseline creation, baseline comparison, or new-finding-only failure thresholds. Pipelines that set baseline, createBaseline, or failOnNew to anything except none fail fast with a validation error instead of pretending to enforce unsupported governance behavior. Baseline support must be added in the scanner repository before this task can forward those inputs.
Additional argument guardrails
additionalArguments is only for supplemental scanner metadata/filtering options. The task rejects attempts to override managed options (--path, --profile, --policy, --format, --output, --sarif, --summary, --fail-on, --snippets, and --no-snippets) so Azure DevOps inputs remain the source of truth for scan target, policy/profile, reports, thresholds, and snippet behavior.
Enterprise agent configuration
Recommended Marketplace defaults are safe for hosted agents: install the scanner into $(Agent.ToolsDirectory)/cerbi-scanner, scan $(Build.SourcesDirectory), publish JSON/SARIF/Markdown reports, suppress snippets with --no-snippets, and only fail when failOn is configured. For regulated or offline environments:
- task: CerbiScan@1
inputs:
scannerVersion: 1.2.0
installScanner: true
scannerInstallDirectory: $(Agent.ToolsDirectory)/cerbi-scanner
packageSource: https://pkgs.dev.azure.com/your-org/_packaging/security/nuget/v3/index.json
installDotNet: true
dotNetVersion: 10.0.x
dotNetInstallDirectory: $(Agent.ToolsDirectory)/dotnet10
scanPath: $(Build.SourcesDirectory)
policyPath: $(Build.SourcesDirectory)/cerbi-policy.yml
failOn: error
reports: markdown,json,sarif
outputDir: $(Build.ArtifactStagingDirectory)/cerbi
includeSnippets: false
publishArtifacts: true
uploadToCerbiShield: false
outputDir is a task-level compatibility input only; the task expands it to explicit scanner output files and does not pass --output-dir. If your self-hosted image already contains an approved scanner, set installScanner: false. The task will resolve the scanner from scannerInstallDirectory, PATH, or the .NET user tools directory without contacting a package feed.
Privacy & security
- The extension delegates to a local scanner process; it does not upload source or findings to a Cerbi service.
- Keep
includeSnippets: falsefor shared reports unless source excerpts are explicitly approved for the pipeline artifact audience. - Pin
scannerVersionin enterprise pipelines for reproducible governance behavior. - Use
packageSourcefor private Azure Artifacts/NuGet feeds or mirrored scanner packages; configure feed credentials through Azure Pipelines service connections or agent NuGet configuration. - Do not route application logs through this extension or any public control-plane service. The scanner is a local CI governance gate only.
Troubleshooting
Missing .NET runtime or SDK
Symptoms usually look like dotnet was not found, You must install or update .NET, or a scanner launch failure after Cerbi.Scanner installs successfully. Fix this in one of three supported ways:
- Preferred for Microsoft-hosted agents: add
UseDotNet@2beforeCerbiScan@1withversion: 10.0.x. - Marketplace fallback: leave
installDotNet: trueso the task installs the .NET 10 SDK into$(Agent.ToolsDirectory)/dotnet10when .NET 10 is missing. - Self-hosted regulated agents: preinstall a pinned .NET 10 SDK/runtime and set
installDotNet: falseonly afterdotnet --list-sdksordotnet --list-runtimesshows a10.0.*entry.
If installScanner: true is enabled, the task needs a .NET SDK, not only a runtime, because dotnet tool install is an SDK command. If installScanner: false and the scanner is preinstalled, a compatible .NET 10 runtime is sufficient to run the tool.
Scanner install failures
- Check
scannerVersionfirst. Uselatestonly when your pipeline accepts new scanner versions at job time; pin an explicit version for regulated builds. - Check
packageSourceand NuGet credentials when using private feeds. - On self-hosted agents without outbound NuGet access, preinstall the scanner and set
installScanner: false.
Unsupported input failures
The task fails fast for inputs that the current scanner does not support, including baseline creation/comparison and new-finding-only thresholds. Remove baseline, createBaseline, and failOnNew values other than none until the scanner implements those capabilities. Do not put task-managed flags in additionalArguments; use the dedicated task inputs instead.
Exact sample YAML
Copy this baseline for the .NET 10 Cerbi.Scanner release:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: UseDotNet@2
displayName: Install .NET 10 SDK
inputs:
packageType: sdk
version: 10.0.x
- task: CerbiScan@1
displayName: Cerbi logging governance scan
inputs:
scanPath: $(Build.SourcesDirectory)
policyPath: $(Build.SourcesDirectory)/cerbi-policy.yml
failOn: error
reports: markdown,json,sarif
outputDir: $(Build.ArtifactStagingDirectory)/cerbi
scannerVersion: latest
installScanner: true
scannerInstallDirectory: $(Agent.ToolsDirectory)/cerbi-scanner
installDotNet: true
dotNetVersion: 10.0.x
dotNetInstallDirectory: $(Agent.ToolsDirectory)/dotnet10
includeSnippets: false
publishArtifacts: true
uploadToCerbiShield: false
Requirements
- Azure DevOps agent with the .NET 10 LTS SDK installed (for example
UseDotNet@2withversion: 10.0.x) or taskinstallDotNet: trueso the task can install it locally. - Network access to the configured NuGet source when
installScanner: true, unless the agent already has the tool installed andinstallScanner: falseis used. - Self-hosted enterprise agents can pin
scannerVersion, setpackageSourceto an internal feed, or disable install and pre-provision the scanner in the agent image.