Skip to content

Commit 229f3a6

Browse files
committed
fix
1 parent be6af54 commit 229f3a6

File tree

2 files changed

+153
-41
lines changed

2 files changed

+153
-41
lines changed

action.yml

Lines changed: 120 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 'GoSecretScan'
2-
description: 'Fast, concurrent secret scanner that detects API keys, credentials, and security vulnerabilities in source code'
2+
description: 'Enterprise-grade secret scanner with 189+ patterns. Scans files AND git history. Detects AWS, GCP, Azure, Stripe, GitHub tokens and more.'
33
author: 'M1RL0K'
44

55
branding:
@@ -11,12 +11,40 @@ inputs:
1111
description: 'Directory path to scan for secrets (default: current directory)'
1212
required: false
1313
default: '.'
14-
fail-on-secrets:
15-
description: 'Fail the workflow if secrets are found (default: true)'
14+
fail-on:
15+
description: 'Minimum confidence level to fail: low, medium, high, critical (default: low = fail on any secret)'
16+
required: false
17+
default: 'low'
18+
output-format:
19+
description: 'Output format: text, json, or sarif (default: text)'
20+
required: false
21+
default: 'text'
22+
sarif-file:
23+
description: 'Path to write SARIF output (for GitHub Security tab integration)'
24+
required: false
25+
default: ''
26+
no-git-history:
27+
description: 'Skip scanning git commit history (default: false, scans entire history)'
28+
required: false
29+
default: 'false'
30+
git-max-commits:
31+
description: 'Maximum commits to scan in git history (0 = all)'
32+
required: false
33+
default: '0'
34+
config:
35+
description: 'Path to config file (.gosecretscanner.json)'
36+
required: false
37+
default: ''
38+
baseline:
39+
description: 'Path to baseline file for suppressing known findings'
40+
required: false
41+
default: ''
42+
redact:
43+
description: 'Redact secret values in output (default: true)'
1644
required: false
1745
default: 'true'
1846
enable-llm:
19-
description: 'Enable LLM-powered verification (requires Docker)'
47+
description: 'Enable LLM-powered verification for fewer false positives (requires Docker)'
2048
required: false
2149
default: 'false'
2250
model-path:
@@ -47,6 +75,9 @@ outputs:
4775
scan-status:
4876
description: 'Status of the scan (success or failed)'
4977
value: ${{ steps.scan.outputs.status }}
78+
sarif-file:
79+
description: 'Path to SARIF output file (if generated)'
80+
value: ${{ steps.scan.outputs.sarif-file }}
5081

5182
runs:
5283
using: 'composite'
@@ -142,17 +173,51 @@ runs:
142173
shell: bash
143174
working-directory: ${{ inputs.scan-path }}
144175
run: |
145-
echo "Running GoSecretScanv2 scanner..."
146-
147-
SECRET_COUNT=0
148-
STATUS="success"
176+
echo "🔍 GoSecretScan - Enterprise Secret Scanner"
177+
echo "==========================================="
149178
150179
SCAN_CMD=("${{ github.action_path }}/gosecretscanner")
151180
181+
# Core options
182+
SCAN_CMD+=("--fail-on=${{ inputs.fail-on }}")
183+
184+
# Output format
185+
OUTPUT_FORMAT="${{ inputs.output-format }}"
186+
SARIF_FILE="${{ inputs.sarif-file }}"
187+
188+
# If SARIF file requested, use sarif output
189+
if [ -n "$SARIF_FILE" ]; then
190+
OUTPUT_FORMAT="sarif"
191+
fi
192+
SCAN_CMD+=("--output=$OUTPUT_FORMAT")
193+
194+
# Redaction
195+
if [ "${{ inputs.redact }}" == "false" ]; then
196+
SCAN_CMD+=("--redact=false")
197+
fi
198+
199+
# Git history options
200+
if [ "${{ inputs.no-git-history }}" == "true" ]; then
201+
SCAN_CMD+=("--no-git-history")
202+
fi
203+
if [ "${{ inputs.git-max-commits }}" != "0" ]; then
204+
SCAN_CMD+=("--git-max-commits=${{ inputs.git-max-commits }}")
205+
fi
206+
207+
# Config file
208+
if [ -n "${{ inputs.config }}" ]; then
209+
SCAN_CMD+=("--config=${{ inputs.config }}")
210+
fi
211+
212+
# Baseline file
213+
if [ -n "${{ inputs.baseline }}" ]; then
214+
SCAN_CMD+=("--baseline=${{ inputs.baseline }}")
215+
fi
216+
217+
# LLM verification
152218
if [ "${{ inputs.enable-llm }}" == "true" ]; then
153219
MODEL_PATH="${{ inputs.model-path }}"
154220
if [[ "$MODEL_PATH" != /* ]]; then
155-
# Resolve to absolute path, removing any ./ prefix
156221
MODEL_PATH="${{ github.action_path }}/${MODEL_PATH#./}"
157222
fi
158223
LLM_ENDPOINT="${{ inputs.llm-endpoint }}"
@@ -162,34 +227,61 @@ runs:
162227
SCAN_CMD+=("--llm" "--model-path=$MODEL_PATH" "--llm-endpoint=$LLM_ENDPOINT")
163228
fi
164229
165-
# Run the scanner and capture output
166-
if "${SCAN_CMD[@]}"; then
167-
echo "No secrets found."
168-
SECRET_COUNT=0
169-
STATUS="success"
230+
echo "Command: ${SCAN_CMD[*]}"
231+
echo ""
232+
233+
# Run the scanner
234+
set +e
235+
if [ -n "$SARIF_FILE" ]; then
236+
"${SCAN_CMD[@]}" > "$SARIF_FILE" 2>&1
237+
exit_code=$?
238+
SECRET_COUNT=$(jq '.runs[0].results | length' "$SARIF_FILE" 2>/dev/null || echo "0")
239+
echo "sarif-file=$SARIF_FILE" >> $GITHUB_OUTPUT
170240
else
241+
OUTPUT=$("${SCAN_CMD[@]}" 2>&1)
171242
exit_code=$?
172-
if [ $exit_code -eq 1 ]; then
173-
echo "Secrets detected!"
174-
SECRET_COUNT=$(grep -c "File:" output.log 2>/dev/null || echo "unknown")
175-
STATUS="failed"
176-
177-
if [ "${{ inputs.fail-on-secrets }}" == "true" ]; then
178-
echo "Failing workflow due to detected secrets."
179-
exit 1
180-
else
181-
echo "Secrets found but not failing workflow (fail-on-secrets=false)"
182-
fi
243+
echo "$OUTPUT"
244+
245+
if [ "$OUTPUT_FORMAT" == "json" ]; then
246+
SECRET_COUNT=$(echo "$OUTPUT" | jq 'length' 2>/dev/null || echo "0")
183247
else
184-
echo "Scanner encountered an error (exit code: $exit_code)"
185-
STATUS="error"
186-
exit $exit_code
248+
SECRET_COUNT=$(echo "$OUTPUT" | grep -c "potential secrets" | head -1 || echo "0")
187249
fi
188250
fi
251+
set -e
252+
253+
# Determine status based on exit code
254+
if [ $exit_code -eq 0 ]; then
255+
echo ""
256+
echo "✅ No secrets found!"
257+
STATUS="success"
258+
SECRET_COUNT=0
259+
elif [ $exit_code -eq 1 ]; then
260+
echo ""
261+
echo "🚨 Secrets detected!"
262+
STATUS="failed"
263+
else
264+
echo ""
265+
echo "❌ Scanner encountered an error (exit code: $exit_code)"
266+
STATUS="error"
267+
exit $exit_code
268+
fi
189269
190270
echo "secrets-found=$SECRET_COUNT" >> $GITHUB_OUTPUT
191271
echo "status=$STATUS" >> $GITHUB_OUTPUT
192272
273+
# Exit with failure if secrets found
274+
if [ $exit_code -eq 1 ]; then
275+
exit 1
276+
fi
277+
278+
- name: Upload SARIF to GitHub Security
279+
if: inputs.sarif-file != '' && always()
280+
uses: github/codeql-action/upload-sarif@v3
281+
with:
282+
sarif_file: ${{ inputs.sarif-file }}
283+
continue-on-error: true
284+
193285
- name: Stop llama.cpp server
194286
if: inputs.enable-llm == 'true' && inputs.manage-llm-server == 'true' && always()
195287
shell: bash

main.go

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ var (
313313
updateBaseline = flag.Bool("update-baseline", false, "Update the baseline file with current findings")
314314
baselineReason = flag.String("baseline-reason", "", "Reason for adding findings to baseline (used with --update-baseline)")
315315

316-
// Git history scanning flags
317-
gitHistory = flag.Bool("git-history", false, "Scan git commit history for secrets")
316+
// Git history scanning flags (git history is scanned by default)
317+
noGitHistory = flag.Bool("no-git-history", false, "Skip scanning git commit history")
318318
gitMaxCommits = flag.Int("git-max-commits", 0, "Maximum number of commits to scan (0 = all, scans entire history)")
319319
gitRef = flag.String("git-ref", "HEAD", "Git ref to start scanning from")
320320
gitSinceDate = flag.String("git-since", "", "Only scan commits after this date (e.g., 2024-01-01)")
@@ -449,18 +449,17 @@ func main() {
449449
}
450450

451451
var secretsFound []Secret
452+
var historySecrets []Secret
452453

453-
// Git history scanning mode
454-
if *gitHistory {
455-
fmt.Printf("Scanning git history (max %d commits from %s)...\n", *gitMaxCommits, *gitRef)
456-
historySecrets, err := scanGitHistory(dir, *gitMaxCommits, *gitRef, *gitSinceDate, pipeline)
457-
if err != nil {
458-
fmt.Printf("%sError scanning git history: %v%s\n", RedColor, err, ResetColor)
459-
os.Exit(1)
460-
}
461-
secretsFound = historySecrets
462-
fmt.Printf("Found %d potential secrets in git history\n", len(secretsFound))
463-
} else {
454+
// Check if we're in a git repo
455+
isGitRepo := false
456+
if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
457+
isGitRepo = true
458+
}
459+
460+
// PHASE 1: Scan current working directory files (with LLM verification if enabled)
461+
fmt.Printf("Phase 1: Scanning current files...\n")
462+
{
464463
// Normal file system scanning
465464
var wg sync.WaitGroup
466465
var mu sync.Mutex
@@ -523,6 +522,27 @@ func main() {
523522

524523
wg.Wait()
525524
}
525+
fmt.Printf("Found %d potential secrets in current files\n", len(secretsFound))
526+
527+
// PHASE 2: Scan git history (no LLM - can't access file content at old commits)
528+
// Git history scanning is ON by default. Use --no-git-history to skip.
529+
if isGitRepo && !*noGitHistory {
530+
fmt.Printf("\nPhase 2: Scanning git history...\n")
531+
var err error
532+
historySecrets, err = scanGitHistory(dir, *gitMaxCommits, *gitRef, *gitSinceDate, nil) // nil pipeline = no LLM
533+
if err != nil {
534+
fmt.Printf("%sWarning: Git history scan failed: %v%s\n", YellowColor, err, ResetColor)
535+
} else {
536+
fmt.Printf("Found %d potential secrets in git history\n", len(historySecrets))
537+
secretsFound = append(secretsFound, historySecrets...)
538+
}
539+
} else if !isGitRepo {
540+
fmt.Printf("\nSkipping git history scan (not a git repository)\n")
541+
} else if *noGitHistory {
542+
fmt.Printf("\nSkipping git history scan (--no-git-history)\n")
543+
}
544+
545+
fmt.Printf("\nTotal: %d potential secrets found\n\n", len(secretsFound))
526546

527547
// Apply config-based filtering (allowlists, disabled rules, entropy threshold)
528548
secretsFound = filterSecretsByConfig(secretsFound, compiledConfig)

0 commit comments

Comments
 (0)