Repository navigation
Expand file tree
/
Copy pathaction.yml
More file actions
102 lines (95 loc) · 4.38 KB
/
Copy pathaction.yml
File metadata and controls
102 lines (95 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
name: Python Security Auditing
description: Run bandit and pip-audit security scans on Python code and report findings
author: Development Seed
inputs:
tools:
description: Comma-separated tools to run (bandit, pip-audit)
default: bandit,pip-audit
bandit_scan_dirs:
description: Comma-separated directories for bandit to scan
default: .
bandit_severity_threshold:
description: Minimum bandit severity that blocks the job (high, medium, low)
default: high
pip_audit_block_on:
description: When to block on pip-audit findings — fixable, all, or none
default: fixable
package_manager:
description: How to resolve dependencies for pip-audit (uv, poetry, pipenv, requirements)
default: requirements
requirements_file:
description: Path to requirements file when package_manager=requirements
default: requirements.txt
comment_on:
description: When to post a PR comment — never, blocking (only when issues block the job), or always
default: 'never'
github_token:
description: GitHub token used for posting PR comments
default: ${{ github.token }}
working_directory:
description: Directory to run the audit from (useful when the project is in a subdirectory)
default: '.'
artifact_name:
description: Name of the artifact uploaded by the action
default: security-audit-reports
debug:
description: Enable debug logging for the Python audit module
default: 'false'
runs:
using: composite
steps:
# A report left by an earlier job (self-hosted runner) must not be uploaded as this one's.
- name: Remove an earlier bandit report
if: contains(inputs.tools, 'bandit')
shell: bash
run: rm -f -- "$GITHUB_WORKSPACE/results.sarif"
# No `python-version` here: it sets UV_PYTHON for the rest of the caller's job, overriding
# their project's Python. The audit step passes --python instead.
- name: Set up uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
- name: Run security audit
id: audit
shell: bash
continue-on-error: true
working-directory: ${{ inputs.working_directory }}
env:
TOOLS: ${{ inputs.tools }}
BANDIT_SCAN_DIRS: ${{ inputs.bandit_scan_dirs }}
BANDIT_SEVERITY_THRESHOLD: ${{ inputs.bandit_severity_threshold }}
BANDIT_SARIF_PATH: ${{ github.workspace }}/results.sarif
PIP_AUDIT_BLOCK_ON: ${{ inputs.pip_audit_block_on }}
PACKAGE_MANAGER: ${{ inputs.package_manager }}
REQUIREMENTS_FILE: ${{ inputs.requirements_file }}
COMMENT_ON: ${{ inputs.comment_on }}
GITHUB_TOKEN: ${{ inputs.github_token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
INPUT_DEBUG: ${{ inputs.debug }}
RUNNER_DEBUG: ${{ runner.debug }}
run: uv run --python 3.13 --no-project --with "$GITHUB_ACTION_PATH" python -m python_security_auditing
# results.sarif exists only if bandit scanned every file in this job: the first step removes
# an earlier one, and the audit deletes it when bandit fails or skips files (an empty or
# partial report would close open alerts). Runs before the artifact upload, so a failed
# upload cannot skip it.
- name: Upload bandit SARIF to Code Scanning
if: contains(inputs.tools, 'bandit') && hashFiles('results.sarif') != ''
continue-on-error: true # needs `security-events: write`; the audit result stands without it
uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
sarif_file: ${{ github.workspace }}/results.sarif
# A job may upload one SARIF per category, so each working_directory gets its own.
# For '.' it stays empty (= no category, the default analysis), as the bandit fork's
# upload did, so existing alerts keep matching.
category: ${{ inputs.working_directory != '.' && format('bandit/{0}', inputs.working_directory) || '' }}
- name: Upload ${{ inputs.artifact_name }}
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: ${{ inputs.artifact_name }}
path: |
${{ inputs.working_directory }}/pip-audit-report.json
${{ github.workspace }}/results.sarif
if-no-files-found: ignore
- name: Fail if blocking issues found
if: steps.audit.outcome == 'failure'
shell: bash
run: exit 1