-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathaction.yml
More file actions
142 lines (130 loc) · 4.75 KB
/
action.yml
File metadata and controls
142 lines (130 loc) · 4.75 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
name: 'VulnHawk Security Scan'
description: 'AI-powered code security scanner that finds vulnerabilities Semgrep and CodeQL miss'
branding:
icon: 'shield'
color: 'red'
inputs:
target:
description: 'Path to scan (file or directory)'
required: false
default: '.'
backend:
description: 'LLM backend (claude, claude-code, openai, codex, ollama)'
required: false
default: 'claude'
model:
description: 'Specific model name'
required: false
mode:
description: 'Scan mode (full, auth, injection, secrets, config, crypto)'
required: false
default: 'full'
severity:
description: 'Minimum severity to report (critical, high, medium, low, info)'
required: false
default: 'medium'
api-key:
description: 'API key for the LLM backend. Not required for claude-code backend.'
required: false
default: ''
claude-code-oauth-token:
description: 'OAuth token for Claude Code CLI backend (free for Claude Code subscribers)'
required: false
default: ''
sarif-input:
description: 'Path to SARIF file from other SAST tools (Semgrep, CodeQL) to enrich VulnHawk analysis'
required: false
default: ''
fail-on-findings:
description: 'Fail the workflow if critical/high findings are detected'
required: false
default: 'true'
sarif-file:
description: 'Path to write SARIF output for GitHub Code Scanning'
required: false
default: 'vulnhawk-results.sarif'
outputs:
findings-count:
description: 'Total number of findings'
value: ${{ steps.scan.outputs.findings-count }}
critical-count:
description: 'Number of critical findings'
value: ${{ steps.scan.outputs.critical-count }}
sarif-file:
description: 'Path to SARIF results file'
value: ${{ inputs.sarif-file }}
runs:
using: 'composite'
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install VulnHawk
shell: bash
run: pip install vulnhawk
- name: Install Claude Code CLI
if: inputs.backend == 'claude-code'
shell: bash
run: npm install -g @anthropic-ai/claude-code
- name: Install Codex CLI
if: inputs.backend == 'codex'
shell: bash
run: npm install -g @openai/codex
- name: Run VulnHawk Scan
id: scan
shell: bash
env:
ANTHROPIC_API_KEY: ${{ inputs.backend == 'claude' && inputs.api-key || '' }}
OPENAI_API_KEY: ${{ inputs.backend == 'openai' && inputs.api-key || '' }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ inputs.backend == 'claude-code' && inputs.claude-code-oauth-token || '' }}
run: |
# Build SARIF input flag if provided
SARIF_INPUT_FLAG=""
if [ -n "${{ inputs.sarif-input }}" ] && [ -f "${{ inputs.sarif-input }}" ]; then
SARIF_INPUT_FLAG="--sarif-input ${{ inputs.sarif-input }}"
fi
# Run scan with SARIF output
vulnhawk scan ${{ inputs.target }} \
--backend ${{ inputs.backend }} \
${{ inputs.model && format('--model {0}', inputs.model) || '' }} \
--mode ${{ inputs.mode }} \
--severity ${{ inputs.severity }} \
--output sarif \
--output-file ${{ inputs.sarif-file }} \
$SARIF_INPUT_FLAG \
--no-progress || true
# Also generate JSON for summary
vulnhawk scan ${{ inputs.target }} \
--backend ${{ inputs.backend }} \
${{ inputs.model && format('--model {0}', inputs.model) || '' }} \
--mode ${{ inputs.mode }} \
--severity ${{ inputs.severity }} \
--output json \
--output-file /tmp/vulnhawk-results.json \
$SARIF_INPUT_FLAG \
--no-progress || true
# Extract counts
if [ -f /tmp/vulnhawk-results.json ]; then
TOTAL=$(python3 -c "import json; d=json.load(open('/tmp/vulnhawk-results.json')); print(d['summary']['total_findings'])")
CRITICAL=$(python3 -c "import json; d=json.load(open('/tmp/vulnhawk-results.json')); print(d['summary']['critical'])")
echo "findings-count=$TOTAL" >> $GITHUB_OUTPUT
echo "critical-count=$CRITICAL" >> $GITHUB_OUTPUT
else
echo "findings-count=0" >> $GITHUB_OUTPUT
echo "critical-count=0" >> $GITHUB_OUTPUT
fi
- name: Upload SARIF to GitHub
if: always() && hashFiles(inputs.sarif-file) != ''
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ inputs.sarif-file }}
- name: Check for critical findings
if: inputs.fail-on-findings == 'true'
shell: bash
run: |
CRITICAL=${{ steps.scan.outputs.critical-count }}
if [ "$CRITICAL" -gt 0 ]; then
echo "::error::VulnHawk found $CRITICAL critical vulnerabilities"
exit 1
fi