Azure DevOps Code Scan
The QualysCodeScan@1 task performs Software Composition Analysis (SCA) on your source code to identify vulnerable dependencies. It supports SBOM generation, secrets detection, and integrates with Azure DevOps Advanced Security.
Task Name: QualysCodeScan@1
Task Inputs
Service Connection
| Input |
Required |
Default |
Description |
qualysConnection |
Yes |
- |
Qualys API service connection name |
Scan Target
| Input |
Required |
Default |
Description |
scanPath |
No |
$(Build.SourcesDirectory) |
Path to the directory to scan |
excludeDirs |
No |
- |
Comma-separated list of directories to exclude |
includeDev |
No |
false |
Include development dependencies |
SBOM Options
| Input |
Required |
Default |
Description |
generateSbom |
No |
false |
Generate a Software Bill of Materials |
sbomFormat |
No |
spdx |
SBOM format: spdx or cyclonedx |
sbomOutput |
No |
sbom.json |
Output filename for the SBOM |
Scan Options
| Input |
Required |
Default |
Description |
scanSecrets |
No |
false |
Enable secrets detection in source code |
offlineMode |
No |
false |
Scan without uploading to Qualys platform |
Threshold Configuration
| Input |
Required |
Default |
Description |
maxCritical |
No |
-1 |
Maximum critical vulnerabilities allowed (-1 = unlimited) |
maxHigh |
No |
-1 |
Maximum high vulnerabilities allowed (-1 = unlimited) |
maxMedium |
No |
-1 |
Maximum medium vulnerabilities allowed (-1 = unlimited) |
maxLow |
No |
-1 |
Maximum low vulnerabilities allowed (-1 = unlimited) |
Policy Configuration
| Input |
Required |
Default |
Description |
usePolicyEvaluation |
No |
false |
Enable Qualys cloud policy evaluation |
failOnAudit |
No |
false |
Fail pipeline when policy result is AUDIT |
Output Options
| Input |
Required |
Default |
Description |
publishResults |
No |
false |
Publish SARIF to Azure DevOps Advanced Security |
Work Item Creation
| Input |
Required |
Default |
Description |
createWorkItems |
No |
false |
Create Azure Boards work items for vulnerabilities |
workItemSeverities |
No |
4,5 |
Severity levels to create work items for |
workItemType |
No |
Bug |
Work item type to create |
workItemAreaPath |
No |
- |
Area path for created work items |
Supported Package Managers
| Language |
Package Manager |
Manifest Files |
| JavaScript/Node.js |
npm, yarn, pnpm |
package.json, package-lock.json, yarn.lock, pnpm-lock.yaml |
| Python |
pip, poetry, pipenv |
requirements.txt, Pipfile.lock, poetry.lock, setup.py |
| Java |
Maven, Gradle |
pom.xml, build.gradle, build.gradle.kts |
| Go |
Go Modules |
go.mod, go.sum |
| .NET |
NuGet |
*.csproj, packages.config, packages.lock.json |
| Ruby |
Bundler |
Gemfile, Gemfile.lock |
| PHP |
Composer |
composer.json, composer.lock |
| Rust |
Cargo |
Cargo.toml, Cargo.lock |
Complete Example
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: QualysCodeScan@1
displayName: 'Qualys Code Scan'
inputs:
qualysConnection: 'QualysConnection'
scanPath: '$(Build.SourcesDirectory)'
excludeDirs: 'node_modules,vendor,test,dist'
includeDev: false
scanSecrets: true
generateSbom: true
sbomFormat: 'spdx'
maxCritical: 0
maxHigh: 10
usePolicyEvaluation: false
publishResults: true
createWorkItems: true
workItemSeverities: '4,5'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- script: |
echo "Vulnerabilities: $(qualysCodeScan.vulnerabilityCount)"
echo "Packages scanned: $(qualysCodeScan.packagesCount)"
echo "Scan passed: $(qualysCodeScan.scanPassed)"
displayName: 'Display Scan Results'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(qualysCodeScan.sbomPath)'
artifactName: 'sbom'
displayName: 'Publish SBOM'
Monorepo Scanning
Scan specific subdirectories in a monorepo:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
Frontend:
projectPath: 'packages/frontend'
Backend:
projectPath: 'packages/backend'
Shared:
projectPath: 'packages/shared'
steps:
- task: QualysCodeScan@1
displayName: 'Scan $(projectPath)'
inputs:
qualysConnection: 'QualysConnection'
scanPath: '$(Build.SourcesDirectory)/$(projectPath)'
generateSbom: true
sbomOutput: 'sbom-$(Build.BuildId).json'
publishResults: true
SBOM Generation Only
Generate an SBOM without vulnerability scanning:
steps:
- task: QualysCodeScan@1
displayName: 'Generate SBOM'
inputs:
qualysConnection: 'QualysConnection'
scanPath: '$(Build.SourcesDirectory)'
generateSbom: true
sbomFormat: 'cyclonedx'
sbomOutput: '$(Build.ArtifactStagingDirectory)/sbom.json'
offlineMode: true
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)/sbom.json'
artifactName: 'sbom'
Output Variables
| Variable |
Description |
$(taskName.vulnerabilityCount) |
Total number of vulnerabilities found |
$(taskName.criticalCount) |
Number of critical vulnerabilities |
$(taskName.highCount) |
Number of high vulnerabilities |
$(taskName.mediumCount) |
Number of medium vulnerabilities |
$(taskName.lowCount) |
Number of low vulnerabilities |
$(taskName.secretsCount) |
Number of secrets detected |
$(taskName.packagesCount) |
Total number of packages/dependencies found |
$(taskName.policyResult) |
Policy result: ALLOW, DENY, AUDIT, or NONE |
$(taskName.scanPassed) |
true/false based on thresholds or policy |
$(taskName.sarifPath) |
Path to SARIF report file |
$(taskName.jsonPath) |
Path to JSON report file |
$(taskName.sbomPath) |
Path to generated SBOM file |
$(taskName.workItemsCreated) |
Number of work items created |
Using Output Variables
steps:
- task: QualysCodeScan@1
name: codeScan
displayName: 'Scan Code'
inputs:
qualysConnection: 'QualysConnection'
scanPath: '$(Build.SourcesDirectory)'
generateSbom: true
- script: |
echo "Total vulnerabilities: $(codeScan.vulnerabilityCount)"
echo "Critical: $(codeScan.criticalCount)"
echo "Packages scanned: $(codeScan.packagesCount)"
echo "Policy result: $(codeScan.policyResult)"
echo "Scan passed: $(codeScan.scanPassed)"
displayName: 'Show Results'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(codeScan.sbomPath)'
artifactName: 'sbom'
displayName: 'Publish SBOM'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(codeScan.sarifPath)'
artifactName: 'security-reports'
displayName: 'Publish SARIF Report'
Multi-Stage Pipeline
trigger:
- main
stages:
- stage: Build
jobs:
- job: BuildApp
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '18.x'
- script: npm ci
- script: npm run build
- stage: Security
dependsOn: Build
jobs:
- job: CodeScan
pool:
vmImage: 'ubuntu-latest'
steps:
- task: QualysCodeScan@1
inputs:
qualysConnection: 'QualysConnection'
scanPath: '$(Build.SourcesDirectory)'
excludeDirs: 'node_modules,dist'
generateSbom: true
maxCritical: 0
publishResults: true
- stage: Deploy
dependsOn: Security
condition: succeeded()
jobs:
- deployment: DeployToProduction
environment: 'production'