microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v3.2.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/security/Invoke-PipAudit.ps1

196lines · modecode

1#!/usr/bin/env pwsh
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4#Requires -Version 7.0
5
6<#
7.SYNOPSIS
8 Runs pip-audit against Python project dependencies for vulnerability scanning.
9
10.DESCRIPTION
11 Discovers Python projects containing pyproject.toml files, exports locked dependencies
12 via uv export, and runs pip-audit to check for known vulnerabilities. Results are written
13 as JSON to the logs directory.
14
15.PARAMETER Path
16 Root path to scan for Python projects. Defaults to repository root.
17
18.PARAMETER OutputPath
19 Directory for JSON results. Defaults to 'logs' under repository root.
20
21.PARAMETER FailOnVulnerability
22 Exit with error code if vulnerabilities are found. Default is false.
23
24.PARAMETER ExcludePaths
25 Comma-separated list of path patterns to exclude from scanning.
26
27.EXAMPLE
28 ./Invoke-PipAudit.ps1
29 Scan all Python projects and report results.
30
31.EXAMPLE
32 ./Invoke-PipAudit.ps1 -FailOnVulnerability
33 Scan and fail if any vulnerabilities are found.
34
35.EXAMPLE
36 ./Invoke-PipAudit.ps1 -Path ".github/skills/experimental/powerpoint"
37 Scan a specific Python project directory.
38#>
39
40[CmdletBinding()]
41param(
42 [Parameter()]
43 [string]$Path = (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)),
44
45 [Parameter()]
46 [string]$OutputPath = (Join-Path (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) 'logs'),
47
48 [Parameter()]
49 [switch]$FailOnVulnerability,
50
51 [Parameter()]
52 [string[]]$ExcludePaths = @()
53)
54
55$ErrorActionPreference = 'Stop'
56
57Import-Module (Join-Path $PSScriptRoot '../lib/Modules/CIHelpers.psm1') -Force
58
59function Find-PythonProjects {
60 <#
61 .SYNOPSIS
62 Discovers Python projects containing pyproject.toml files.
63 #>
64 [CmdletBinding()]
65 param(
66 [Parameter(Mandatory)]
67 [string]$SearchPath,
68
69 [Parameter()]
70 [string[]]$Exclude = @()
71 )
72
73 @(Get-ChildItem -Path $SearchPath -Recurse -Force -Filter pyproject.toml |
74 Where-Object { $_.FullName -notmatch 'node_modules' } |
75 ForEach-Object { $_.DirectoryName } |
76 Where-Object {
77 $dir = $_
78 $excluded = $false
79 foreach ($pattern in $Exclude) {
80 if ($dir -like "*$pattern*") { $excluded = $true; break }
81 }
82 -not $excluded
83 } |
84 Sort-Object)
85}
86
87function Invoke-PipAuditForProject {
88 <#
89 .SYNOPSIS
90 Runs pip-audit against a single Python project directory.
91 #>
92 [CmdletBinding()]
93 param(
94 [Parameter(Mandatory)]
95 [string]$ProjectPath,
96
97 [Parameter(Mandatory)]
98 [string]$OutputPath
99 )
100
101 $name = (Resolve-Path -Relative $ProjectPath) -replace '[\\/]', '-' -replace '^\.', '' -replace '^-', ''
102 $requirementsFile = Join-Path ([System.IO.Path]::GetTempPath()) "requirements-$name.txt"
103 $resultsFile = Join-Path $OutputPath "pip-audit-$name.json"
104
105 Write-Host "Auditing: $ProjectPath"
106
107 # Export locked dependencies
108 Push-Location $ProjectPath
109 try {
110 uv export --format requirements-txt --no-hashes > $requirementsFile
111 } finally {
112 Pop-Location
113 }
114
115 # Run pip-audit; finally block ensures temp file cleanup on terminating errors
116 try {
117 uvx pip-audit@2.10.0 `
118 -r $requirementsFile `
119 --no-deps `
120 --format json `
121 -o $resultsFile `
122 --desc on `
123 --aliases on `
124 --progress-spinner off `
125 --strict
126
127 $exitCode = $LASTEXITCODE
128 } finally {
129 if (Test-Path $requirementsFile) { Remove-Item $requirementsFile }
130 }
131
132 if ($exitCode -ne 0) {
133 Write-Host "::warning::Vulnerabilities found in $ProjectPath"
134 return $true # has vulnerabilities
135 }
136
137 Write-Host "No vulnerabilities found in $ProjectPath"
138 return $false
139}
140
141function Start-PipAudit {
142 <#
143 .SYNOPSIS
144 Orchestrates pip-audit scanning across discovered Python projects.
145 .OUTPUTS
146 System.Int32 - 0 for success, 1 when vulnerabilities found and FailOnVulnerability is set.
147 #>
148 [CmdletBinding()]
149 param(
150 [Parameter(Mandatory)]
151 [string]$SearchPath,
152
153 [Parameter(Mandatory)]
154 [string]$OutputPath,
155
156 [Parameter()]
157 [switch]$FailOnVulnerability,
158
159 [Parameter()]
160 [string[]]$ExcludePaths = @()
161 )
162
163 $projects = @(Find-PythonProjects -SearchPath $SearchPath -Exclude $ExcludePaths)
164
165 if ($projects.Count -eq 0) {
166 Write-Host 'No Python projects found'
167 return 0
168 }
169
170 Write-Host "Found $($projects.Count) Python project(s)"
171
172 New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
173
174 $hasVulnerabilities = $false
175
176 foreach ($project in $projects) {
177 if (Invoke-PipAuditForProject -ProjectPath $project -OutputPath $OutputPath) {
178 $hasVulnerabilities = $true
179 }
180 }
181
182 Write-Host "Results written to $OutputPath"
183
184 if ($hasVulnerabilities -and $FailOnVulnerability) {
185 Write-Host '::error::pip-audit found vulnerabilities in one or more Python projects'
186 return 1
187 }
188
189 return 0
190}
191
192# Dot-source guard: skip main execution when dot-sourced for testing
193if ($MyInvocation.InvocationName -ne '.') {
194 $result = Start-PipAudit -SearchPath $Path -OutputPath $OutputPath -FailOnVulnerability:$FailOnVulnerability -ExcludePaths $ExcludePaths
195 if ($result -ne 0) { exit $result }
196}