-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaction.yml
More file actions
147 lines (136 loc) · 5.22 KB
/
Copy pathaction.yml
File metadata and controls
147 lines (136 loc) · 5.22 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
name: Python security scan (reachability-filtered pip-audit)
description: >-
Run pip-audit against a uv-managed Python project, then use pi
(pi-coding-agent) + an OpenRouter LLM to filter the findings down to
vulnerabilities that are actually reachable from this project's declared
entry points. Diffs against a cached state file so only newly-introduced
reachable CVEs are surfaced. Python-specific: requires a pyproject.toml at
the project root (the repo root, or `working-directory` for monorepos),
scans the resolved Python dependency graph, and the reachability prompt
assumes Python module/import semantics.
author: peakford
branding:
icon: shield
color: blue
inputs:
project-name:
description: >-
Project identifier. Used as the state filename (`<project>.json`) and as
the default Pushover notification title prefix. Casing is preserved
verbatim, so pass `MyProject` rather than `myproject` if you want that.
required: true
entry-points:
description: >-
Multi-line text injected into the pi reachability prompt under
"Entry points to consider". Describe how this project's code is
actually invoked (HTTP handlers, task queues, CLI entry points,
import-time module code, etc.). Required — no default, since defaults
tend to bleed stale framework assumptions across projects.
required: true
model:
description: >-
OpenRouter model id, passed to pi as `--provider openrouter --model
<id>`.
required: false
default: z-ai/glm-5.1
notify:
description: >-
Whether to deliver a Pushover alert when a new reachable CVE is found.
Requires PUSHOVER_USER_KEY + PUSHOVER_APP_KEY env in the calling job.
required: false
default: 'true'
notification-title:
description: >-
Pushover notification title. Defaults to `<project-name>: new reachable CVE`
when empty.
required: false
default: ''
state-key-file:
description: >-
File whose hash is used as the cache key for the persisted scan state
(so a lockfile change invalidates and forces re-scoring of every vuln).
Resolved relative to `working-directory`.
required: false
default: uv.lock
working-directory:
description: >-
Subdirectory containing the Python project to scan (its pyproject.toml
and lockfile), relative to the repository root. Set this for monorepos;
defaults to the repo root. Both pip-audit and the reachability scan are
scoped to this directory.
required: false
default: '.'
python-script-args:
description: Escape hatch for extra CLI flags forwarded to security_scan_ci.py.
required: false
default: ''
runs:
using: composite
steps:
- name: Set up uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
# Retain pre-built wheels across runs (pip-audit + its deps, project
# deps) instead of re-downloading them each scan; the default
# `uv cache prune --ci` would drop them.
prune-cache: false
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- name: Compute pi cache key (rotates weekly)
id: pi-key
shell: bash
run: echo "week=$(date -u +%G-%V)" >> "$GITHUB_OUTPUT"
- name: Cache pi
uses: actions/cache@v4
with:
path: ~/.pi-npm
key: pi-earendil-${{ runner.os }}-${{ steps.pi-key.outputs.week }}
- name: Install pi
shell: bash
run: |
npm config set prefix "$HOME/.pi-npm"
echo "$HOME/.pi-npm/bin" >> "$GITHUB_PATH"
if ! [ -x "$HOME/.pi-npm/bin/pi" ]; then
npm install -g @earendil-works/pi-coding-agent
fi
- name: Resolve state directory
id: state
shell: bash
run: |
dir="${STATE_DIR:-$GITHUB_WORKSPACE/.security-state}"
echo "dir=$dir" >> "$GITHUB_OUTPUT"
echo "STATE_DIR=$dir" >> "$GITHUB_ENV"
- name: Restore CVE state cache
uses: actions/cache/restore@v4
with:
path: ${{ steps.state.outputs.dir }}
key: pip-audit-state-${{ hashFiles(format('{0}/{1}', inputs.working-directory, inputs.state-key-file)) }}-${{ github.run_id }}
restore-keys: |
pip-audit-state-${{ hashFiles(format('{0}/{1}', inputs.working-directory, inputs.state-key-file)) }}-
pip-audit-state-
- name: Run reachability scan
id: scan
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
SCAN_PROJECT: ${{ inputs.project-name }}
SCAN_ENTRY_POINTS: ${{ inputs.entry-points }}
SCAN_MODEL: ${{ inputs.model }}
SCAN_NOTIFICATION_TITLE: ${{ inputs.notification-title }}
run: |
notify_flag=""
if [ "${{ inputs.notify }}" = "true" ]; then
notify_flag="--notify"
fi
# shellcheck disable=SC2086
uv run python "$GITHUB_ACTION_PATH/scripts/security_scan_ci.py" \
$notify_flag ${{ inputs.python-script-args }}
- name: Save CVE state cache
if: always()
uses: actions/cache/save@v4
with:
path: ${{ steps.state.outputs.dir }}
key: pip-audit-state-${{ hashFiles(format('{0}/{1}', inputs.working-directory, inputs.state-key-file)) }}-${{ github.run_id }}