forked from gensecaihq/react2shell-scanner
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaction.yml
More file actions
302 lines (250 loc) · 9.99 KB
/
action.yml
File metadata and controls
302 lines (250 loc) · 9.99 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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
name: 'React2Shell Guard - CVE-2025-55182 Scanner'
description: 'Scan for CVE-2025-55182 - Critical RCE in React Server Components. Detects vulnerable Next.js/React packages.'
author: 'GenSecAI'
branding:
icon: 'shield'
color: 'red'
inputs:
path:
description: 'Path to scan (default: current directory)'
required: false
default: '.'
scan-type:
description: 'Type of scan: repo, sbom, or container'
required: false
default: 'repo'
sbom-file:
description: 'Path to CycloneDX SBOM file (when scan-type is sbom)'
required: false
default: ''
container-image:
description: 'Docker image to scan (when scan-type is container)'
required: false
default: ''
format:
description: 'Output format: text, json, or sarif'
required: false
default: 'text'
fail-on-vuln:
description: 'Fail the action if vulnerabilities are found'
required: false
default: 'true'
upload-sarif:
description: 'Upload SARIF results to GitHub Security tab (requires format: sarif)'
required: false
default: 'false'
ignore-paths:
description: 'Comma-separated list of paths to ignore (glob patterns)'
required: false
default: ''
add-pr-comment:
description: 'Add a comment to the PR with scan results'
required: false
default: 'false'
github-token:
description: 'GitHub token for PR comments (defaults to github.token)'
required: false
default: ${{ github.token }}
outputs:
vulnerable:
description: 'Whether vulnerabilities were found (true/false)'
value: ${{ steps.scan.outputs.vulnerable }}
findings-count:
description: 'Number of vulnerable packages found'
value: ${{ steps.scan.outputs.findings_count }}
scan-result:
description: 'Full scan result in JSON format'
value: ${{ steps.scan.outputs.scan_result }}
sarif-file:
description: 'Path to SARIF output file (if format is sarif)'
value: ${{ steps.scan.outputs.sarif_file }}
runs:
using: 'composite'
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install react2shell-guard
shell: bash
run: |
echo "::group::Installing react2shell-guard"
npm install -g react2shell-guard@latest
echo "Installed version: $(react2shell-guard --version)"
echo "::endgroup::"
- name: Run security scan
id: scan
shell: bash
env:
INPUT_PATH: ${{ inputs.path }}
INPUT_SCAN_TYPE: ${{ inputs.scan-type }}
INPUT_SBOM_FILE: ${{ inputs.sbom-file }}
INPUT_CONTAINER_IMAGE: ${{ inputs.container-image }}
INPUT_FORMAT: ${{ inputs.format }}
INPUT_FAIL_ON_VULN: ${{ inputs.fail-on-vuln }}
INPUT_IGNORE_PATHS: ${{ inputs.ignore-paths }}
run: |
set +e
# Build command based on scan type
CMD="react2shell-guard"
case "$INPUT_SCAN_TYPE" in
"sbom")
if [ -z "$INPUT_SBOM_FILE" ]; then
echo "::error::sbom-file is required when scan-type is sbom"
exit 1
fi
CMD="$CMD scan-sbom $INPUT_SBOM_FILE"
;;
"container")
if [ -z "$INPUT_CONTAINER_IMAGE" ]; then
echo "::error::container-image is required when scan-type is container"
exit 1
fi
CMD="$CMD scan-image $INPUT_CONTAINER_IMAGE"
;;
*)
CMD="$CMD scan $INPUT_PATH"
;;
esac
# Add format flag
if [ "$INPUT_FORMAT" = "json" ]; then
CMD="$CMD --json"
elif [ "$INPUT_FORMAT" = "sarif" ]; then
CMD="$CMD --sarif"
fi
# Add ignore paths
if [ -n "$INPUT_IGNORE_PATHS" ]; then
IFS=',' read -ra PATHS <<< "$INPUT_IGNORE_PATHS"
for path in "${PATHS[@]}"; do
CMD="$CMD --ignore-path $(echo $path | xargs)"
done
fi
# Always use --no-exit-on-vuln to capture output
CMD="$CMD --no-exit-on-vuln"
echo "::group::Running scan"
echo "Command: $CMD"
# Run scan and capture output
OUTPUT=$($CMD 2>&1)
SCAN_EXIT=$?
echo "$OUTPUT"
echo "::endgroup::"
# Determine vulnerability status
VULNERABLE="false"
FINDINGS_COUNT="0"
if echo "$OUTPUT" | grep -qE '"vulnerable":\s*true|VULNERABLE'; then
VULNERABLE="true"
# Count findings from output
FINDINGS_COUNT=$(echo "$OUTPUT" | grep -c "Upgrade to:" || echo "0")
fi
# Set outputs
echo "vulnerable=$VULNERABLE" >> $GITHUB_OUTPUT
echo "findings_count=$FINDINGS_COUNT" >> $GITHUB_OUTPUT
# Save JSON result for output
if [ "$INPUT_FORMAT" = "json" ]; then
echo "scan_result<<EOF" >> $GITHUB_OUTPUT
echo "$OUTPUT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
# Save SARIF file
if [ "$INPUT_FORMAT" = "sarif" ]; then
SARIF_FILE="react2shell-guard-results.sarif"
echo "$OUTPUT" > "$SARIF_FILE"
echo "sarif_file=$SARIF_FILE" >> $GITHUB_OUTPUT
fi
# Create Job Summary
echo "## 🛡️ React2Shell Guard Scan Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$VULNERABLE" = "true" ]; then
echo "### ❌ Vulnerabilities Detected!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**CVE-2025-55182** - Critical RCE vulnerability found in your dependencies." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Vulnerable Packages | $FINDINGS_COUNT |" >> $GITHUB_STEP_SUMMARY
echo "| Severity | **CRITICAL (CVSS 10.0)** |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "#### Recommended Actions:" >> $GITHUB_STEP_SUMMARY
echo "1. Upgrade affected packages to patched versions immediately" >> $GITHUB_STEP_SUMMARY
echo "2. Run \`npx react2shell-guard fix\` to auto-fix vulnerabilities" >> $GITHUB_STEP_SUMMARY
echo "3. Review the [security advisory](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Add annotations for vulnerabilities
echo "::error title=CVE-2025-55182 Vulnerability Detected::Found $FINDINGS_COUNT vulnerable package(s). Upgrade immediately to prevent RCE attacks."
else
echo "### ✅ No Vulnerabilities Found" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Your project is not affected by CVE-2025-55182." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "*Scanned with [react2shell-guard](https://github.com/gensecaihq/react2shell-scanner) v$(react2shell-guard --version 2>/dev/null | head -1 || echo '1.1.0')*" >> $GITHUB_STEP_SUMMARY
# Exit based on vulnerability status
if [ "$VULNERABLE" = "true" ] && [ "$INPUT_FAIL_ON_VULN" = "true" ]; then
exit 1
fi
exit 0
- name: Upload SARIF to GitHub Security
if: inputs.upload-sarif == 'true' && inputs.format == 'sarif' && always()
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: react2shell-guard-results.sarif
category: react2shell-guard
continue-on-error: true
- name: Add PR Comment
if: inputs.add-pr-comment == 'true' && github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
with:
github-token: ${{ inputs.github-token }}
script: |
const vulnerable = '${{ steps.scan.outputs.vulnerable }}' === 'true';
const findingsCount = '${{ steps.scan.outputs.findings_count }}';
let body = '';
if (vulnerable) {
body = `## 🚨 Security Alert: CVE-2025-55182 Detected
**react2shell-guard** found **${findingsCount}** vulnerable package(s) in this PR.
### What is CVE-2025-55182?
A critical (CVSS 10.0) Remote Code Execution vulnerability in React Server Components that allows unauthenticated attackers to execute arbitrary code.
### Affected Packages
- \`next\`: 15.0.0-15.0.2, 15.1.0, 16.0.0-16.0.6
- \`react-server-dom-webpack\`: 19.0.0-19.1.0
- \`react-server-dom-turbopack\`: 19.0.0-19.1.0
### How to Fix
\`\`\`bash
npx react2shell-guard fix
\`\`\`
Or manually upgrade to patched versions.
---
*🛡️ Scanned by [react2shell-guard](https://github.com/gensecaihq/react2shell-scanner)*`;
} else {
body = `## ✅ Security Scan Passed
**react2shell-guard** found no CVE-2025-55182 vulnerabilities in this PR.
---
*🛡️ Scanned by [react2shell-guard](https://github.com/gensecaihq/react2shell-scanner)*`;
}
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const existingComment = comments.find(c =>
c.user.type === 'Bot' &&
c.body.includes('react2shell-guard')
);
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
continue-on-error: true