Skip to content

Instantly share code, notes, and snippets.

@mocella
Created November 9, 2022 13:37
Show Gist options
  • Save mocella/f9be8a3b907f9147c93cea6316447bcd to your computer and use it in GitHub Desktop.
Save mocella/f9be8a3b907f9147c93cea6316447bcd to your computer and use it in GitHub Desktop.
Azure Pipeline Step to Scan for .NET Dependency CVEs
- task: PowerShell@2
displayName: "NuGet packages vulnerabilities scan"
continueOnError: false
inputs:
filePath: '$(Build.SourcesDirectory)/nuget-vunerability-build-fail-report.ps1'
arguments: '''$(Build.SourcesDirectory)'' ''$(SolutionName)'''
pwsh: true
# based on article: https://dejanstojanovic.net/aspnet/2022/june/using-dotnet-nuget-package-vulnerability-scan-in-azure-devops-build/
$workingFolder = $args[0]
$solution = $args[1]
$processrocessInfo = New-Object System.Diagnostics.ProcessStartInfo
$processrocessInfo.FileName = "dotnet"
$processrocessInfo.RedirectStandardError = $true
$processrocessInfo.RedirectStandardOutput = $true
$processrocessInfo.UseShellExecute = $false
$processrocessInfo.WorkingDirectory = $workingFolder
$packageListCommand = 'list ./' + $solution + ' package --vulnerable --include-transitive'
$output=''
$summary='# Nuget package vulnerability scan summary';
$processrocessInfo.Arguments = $packageListCommand
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $processrocessInfo
$process.Start() | Out-Null
$stdout = $process.StandardOutput.ReadToEnd()
$stderr = $process.StandardError.ReadToEnd()
$process.WaitForExit()
$output = $output + $stdout + [Environment]::NewLine
echo $output
$leadingString = ' > '
$outputLines = $output -split [Environment]::NewLine
$vulnerabilityDetected = $false
foreach ($line in $outputLines) {
if($line.StartsWith('Project ')){
$projectName = $line.Split('`')[1]
$summary = $summary + [Environment]::NewLine + [Environment]::NewLine + '## ' + $projectName + [Environment]::NewLine + [Environment]::NewLine
$summary = $summary + "| Package | Resolved | Severity | Advisory URL |" + [Environment]::NewLine
$summary = $summary + "|:--------|:--------:|--------|--------|"
}
if($line.StartsWith($leadingString)){
# replace ranges of spaces with a single space so we can split and receive an expected count of 4 or 5 elements in the $columns array
$packageLine = $line.Substring($leadingString.Length) -replace '\s+', ' '
$columns = $packageLine.Split(" ")
$row = "| "
$columnCount = 0
foreach($column in $columns){
if($column.Length -gt 1 ){
$columnCount = $columnCount + 1
$value = $column.Trim()
if($value.StartsWith('http')){
$value = "[" + $value + "](" + $value + ")"
}
# top-level results have 5 elements (an extra version element), transitive results have 4 elements
if(($columns.Count -eq 5 -and $columnCount -ne 3) -or ($columns.Count -ne 5)){
$row = $row + $value + " |"
}
}
}
$summary = $summary + [Environment]::NewLine + $row
# Opting to key off of High and Critical vulnerabilities to cause a step fail/vulnerability-detected condition:
if($packageLine.Contains(" High ") -or $packageLine.Contains(" Critical ")){
if($vulnerabilityDetected -eq $false){
$vulnerabilityDetected = $true
}
}
}
}
# Write to file
$summaryPath = $workingFolder + "/nuget-vulnerabilty-report.md"
Set-Content -Path $summaryPath -Value $summary
# Push to Azure DevOps
$summaryOut = "##vso[task.uploadsummary]" + $summaryPath
Write-Host $summaryOut
if($vulnerabilityDetected){
throw "Vulnerability detected!"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment