Created
November 9, 2022 13:37
-
-
Save mocella/f9be8a3b907f9147c93cea6316447bcd to your computer and use it in GitHub Desktop.
Azure Pipeline Step to Scan for .NET Dependency CVEs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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