Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions .github/workflows/secret-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: Secret Scanning

on:
pull_request:
push:
branches: [main, master]
schedule:
- cron: '0 9 * * 1'

jobs:
gitleaks:
name: Gitleaks
runs-on: ubuntu-latest
outputs:
secrets_found: ${{ steps.count.outputs.secrets_found }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install Gitleaks
run: |
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz" \
| tar xz -C /usr/local/bin gitleaks

- name: Write org-wide allowlist
run: |
cat > .gitleaks.toml << 'GITLEAKS_EOF'
[extend]
useDefault = true

[allowlist]
paths = [
'''db/structure\.sql''',
'''db/schema\.rb''',
'''routesforllms\.txt''',
'''\.sarif$''',
]
regexes = [
'''pk\.eyJ1''',
'''YOUR_API_KEY''',
'''YOUR_CLIENT_ID''',
]
GITLEAKS_EOF

- name: Run Gitleaks
id: scan
run: |
gitleaks detect \
--source . \
--config .gitleaks.toml \
--report-format sarif \
--report-path gitleaks-results.sarif \
--exit-code 2
continue-on-error: true

- name: Count findings
id: count
if: always()
run: |
if [ -f gitleaks-results.sarif ]; then
COUNT=$(jq '[.runs[].results[]] | length' gitleaks-results.sarif 2>/dev/null || echo 0)
else
COUNT=0
fi
echo "secrets_found=$COUNT" >> "$GITHUB_OUTPUT"

- name: Upload SARIF to Security tab
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: gitleaks-results.sarif
continue-on-error: true

- name: Upload scan artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: gitleaks-results
path: gitleaks-results.sarif

- name: Fail if secrets found
if: steps.scan.outcome == 'failure'
run: exit 1

trufflehog:
name: TruffleHog (Verified Secrets)
runs-on: ubuntu-latest
outputs:
secrets_found: ${{ steps.count.outputs.secrets_found }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: TruffleHog Scan
id: scan
uses: trufflesecurity/trufflehog@v3.88.1
with:
extra_args: --only-verified
continue-on-error: true

- name: Set result
id: count
if: always()
run: |
if [ "${{ steps.scan.outcome }}" = "failure" ]; then
echo "secrets_found=1" >> "$GITHUB_OUTPUT"
else
echo "secrets_found=0" >> "$GITHUB_OUTPUT"
fi

- name: Fail if secrets found
if: steps.scan.outcome == 'failure'
run: exit 1

report-to-drata:
name: Report to Drata
runs-on: ubuntu-latest
needs: [gitleaks, trufflehog]
if: always()
env:
DRATA_CONNECTION_ID: 11
DRATA_CCT_API_KEY: ${{ secrets.DRATA_CCT_API_KEY }}
steps:
- name: Get resource ID
if: env.DRATA_CCT_API_KEY != ''
id: resource
run: |
RESOURCE_ID=$(curl -sf \
-H "Authorization: Bearer ${{ env.DRATA_CCT_API_KEY }}" \
"https://public-api.drata.com/public/v2/custom-connections/${{ env.DRATA_CONNECTION_ID }}?expand[]=customResources" \
| jq -r '.customResources[0].id')
echo "id=$RESOURCE_ID" >> "$GITHUB_OUTPUT"

- name: Submit scan results
if: env.DRATA_CCT_API_KEY != ''
run: |
GITLEAKS=${{ needs.gitleaks.outputs.secrets_found || 0 }}
TRUFFLEHOG=${{ needs.trufflehog.outputs.secrets_found || 0 }}
TOTAL=$((GITLEAKS + TRUFFLEHOG))
if [ "$TOTAL" -eq 0 ]; then PASSED=true; else PASSED=false; fi

curl -sf -X POST \
-H "Authorization: Bearer ${{ env.DRATA_CCT_API_KEY }}" \
-H "Content-Type: application/json" \
"https://public-api.drata.com/public/v2/custom-connections/${{ env.DRATA_CONNECTION_ID }}/resources/${{ steps.resource.outputs.id }}/records" \
-d "$(jq -n \
--arg repo "${{ github.repository }}" \
--arg scan_id "${{ github.repository }}-${{ github.run_id }}" \
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg sha "${{ github.sha }}" \
--arg trigger "${{ github.event_name }}" \
--argjson gitleaks "$GITLEAKS" \
--argjson trufflehog "$TRUFFLEHOG" \
--argjson total "$TOTAL" \
--argjson passed "$PASSED" \
--arg url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
'{data: {
repo_name: $repo,
scan_id: $scan_id,
scan_timestamp: $ts,
commit_sha: $sha,
trigger: $trigger,
gitleaks_secrets_found: $gitleaks,
trufflehog_verified_secrets_found: $trufflehog,
total_secrets_found: $total,
passed: $passed,
workflow_run_url: $url
}}'
)"
Loading