Skip to content

Commit a9459a0

Browse files
committed
Move action.yml to repo root for Marketplace, update refs to @v0.3.1
1 parent 1a81a94 commit a9459a0

3 files changed

Lines changed: 128 additions & 2 deletions

File tree

.github/workflows/example-usage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
steps:
1515
- uses: actions/checkout@v4
1616

17-
- uses: Data-ScienceTech/forcefield/.github/actions/forcefield@main
17+
- uses: Data-ScienceTech/forcefield@v0.3.1
1818
with:
1919
mode: 'both'
2020
sensitivity: 'medium'

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
runs-on: ubuntu-latest
153153
steps:
154154
- uses: actions/checkout@v4
155-
- uses: Data-ScienceTech/forcefield/.github/actions/forcefield@main
155+
- uses: Data-ScienceTech/forcefield@v0.3.1
156156
with:
157157
mode: 'both' # selftest + audit
158158
sensitivity: 'medium'

action.yml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
name: 'ForceField AI Security Scanner'
2+
description: 'Scan your codebase and LLM prompts for prompt injection, PII leaks, and security vulnerabilities.'
3+
author: 'Data Science Technologies'
4+
5+
branding:
6+
icon: 'shield'
7+
color: 'green'
8+
9+
inputs:
10+
mode:
11+
description: 'Scan mode: selftest, audit, or both'
12+
required: false
13+
default: 'both'
14+
sensitivity:
15+
description: 'Detection sensitivity: low, medium, high, critical'
16+
required: false
17+
default: 'medium'
18+
audit-path:
19+
description: 'Path to scan for hardcoded prompts and PII (used in audit mode)'
20+
required: false
21+
default: 'src/'
22+
install-extras:
23+
description: 'pip extras to install (e.g. ml, all)'
24+
required: false
25+
default: 'ml'
26+
fail-on-detection:
27+
description: 'Fail the workflow if selftest detection rate drops below threshold'
28+
required: false
29+
default: 'true'
30+
detection-threshold:
31+
description: 'Minimum detection rate (0-100) to pass. Only used if fail-on-detection is true.'
32+
required: false
33+
default: '95'
34+
python-version:
35+
description: 'Python version to use'
36+
required: false
37+
default: '3.12'
38+
39+
outputs:
40+
detection-rate:
41+
description: 'Selftest detection rate (e.g. 100)'
42+
value: ${{ steps.selftest.outputs.detection_rate }}
43+
detected:
44+
description: 'Number of attacks detected'
45+
value: ${{ steps.selftest.outputs.detected }}
46+
total:
47+
description: 'Total number of attacks tested'
48+
value: ${{ steps.selftest.outputs.total }}
49+
audit-issues:
50+
description: 'Number of audit issues found'
51+
value: ${{ steps.audit.outputs.issues }}
52+
53+
runs:
54+
using: 'composite'
55+
steps:
56+
- name: Set up Python
57+
uses: actions/setup-python@v5
58+
with:
59+
python-version: ${{ inputs.python-version }}
60+
61+
- name: Install ForceField
62+
shell: bash
63+
run: |
64+
pip install --quiet "forcefield[${{ inputs.install-extras }}]"
65+
66+
- name: Run selftest
67+
id: selftest
68+
if: inputs.mode == 'selftest' || inputs.mode == 'both'
69+
shell: bash
70+
run: |
71+
echo "::group::ForceField Selftest"
72+
OUTPUT=$(forcefield selftest --sensitivity ${{ inputs.sensitivity }} 2>&1) || true
73+
echo "$OUTPUT"
74+
echo "::endgroup::"
75+
76+
# Parse detection rate from output
77+
RATE=$(echo "$OUTPUT" | grep -oP '\d+(?=/\d+)' | head -1)
78+
TOTAL=$(echo "$OUTPUT" | grep -oP '(?<=/)\d+' | head -1)
79+
if [ -n "$RATE" ] && [ -n "$TOTAL" ]; then
80+
PCT=$(( RATE * 100 / TOTAL ))
81+
echo "detection_rate=$PCT" >> $GITHUB_OUTPUT
82+
echo "detected=$RATE" >> $GITHUB_OUTPUT
83+
echo "total=$TOTAL" >> $GITHUB_OUTPUT
84+
85+
echo "### ForceField Selftest Results" >> $GITHUB_STEP_SUMMARY
86+
echo "" >> $GITHUB_STEP_SUMMARY
87+
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
88+
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
89+
echo "| Detection Rate | **${PCT}%** (${RATE}/${TOTAL}) |" >> $GITHUB_STEP_SUMMARY
90+
echo "| Sensitivity | ${{ inputs.sensitivity }} |" >> $GITHUB_STEP_SUMMARY
91+
echo "" >> $GITHUB_STEP_SUMMARY
92+
93+
if [ "${{ inputs.fail-on-detection }}" = "true" ]; then
94+
THRESHOLD=${{ inputs.detection-threshold }}
95+
if [ "$PCT" -lt "$THRESHOLD" ]; then
96+
echo "::error::Detection rate ${PCT}% is below threshold ${THRESHOLD}%"
97+
exit 1
98+
fi
99+
fi
100+
fi
101+
102+
- name: Run audit
103+
id: audit
104+
if: inputs.mode == 'audit' || inputs.mode == 'both'
105+
shell: bash
106+
run: |
107+
AUDIT_PATH="${{ inputs.audit-path }}"
108+
if [ -d "$AUDIT_PATH" ]; then
109+
echo "::group::ForceField Audit ($AUDIT_PATH)"
110+
OUTPUT=$(forcefield audit "$AUDIT_PATH" --json 2>&1) || true
111+
echo "$OUTPUT"
112+
echo "::endgroup::"
113+
114+
ISSUES=$(echo "$OUTPUT" | grep -c '"severity"' || echo "0")
115+
echo "issues=$ISSUES" >> $GITHUB_OUTPUT
116+
117+
echo "### ForceField Audit Results" >> $GITHUB_STEP_SUMMARY
118+
echo "" >> $GITHUB_STEP_SUMMARY
119+
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
120+
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
121+
echo "| Path Scanned | \`${AUDIT_PATH}\` |" >> $GITHUB_STEP_SUMMARY
122+
echo "| Issues Found | **${ISSUES}** |" >> $GITHUB_STEP_SUMMARY
123+
else
124+
echo "::warning::Audit path '$AUDIT_PATH' not found, skipping audit"
125+
echo "issues=0" >> $GITHUB_OUTPUT
126+
fi

0 commit comments

Comments
 (0)