Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
43162b1
Add TruffleHog secret scanning workflow and docs
GAdityaVarma Jan 7, 2026
200cee2
Update README.md
GAdityaVarma Jan 7, 2026
bf7b85b
Update trufflehog-scan.yml
GAdityaVarma Jan 7, 2026
527f3f2
Update trufflehog-scan.yml
GAdityaVarma Jan 7, 2026
599658f
Update trufflehog-scan.yml
GAdityaVarma Jan 7, 2026
f42179b
Enhance TruffleHog workflow with PR comments and commit status
GAdityaVarma Jan 7, 2026
e496bac
Update trufflehog_readme.md
GAdityaVarma Jan 7, 2026
d279b66
Update trufflehog-scan.yml
GAdityaVarma Jan 8, 2026
1aae01b
Update trufflehog-scan.yml
GAdityaVarma Jan 8, 2026
77909eb
Update trufflehog-scan.yml
GAdityaVarma Jan 8, 2026
c120b09
Update trufflehog-scan.yml
GAdityaVarma Jan 8, 2026
174b7d0
Update TruffleHog workflow to handle resolved secrets
GAdityaVarma Jan 8, 2026
7ded023
Update trufflehog-scan.yml
GAdityaVarma Jan 8, 2026
40260d7
Update trufflehog-scan.yml
GAdityaVarma Jan 8, 2026
5907188
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
c38506c
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
6f0f819
Remove workflow_dispatch trigger for ruleset compatibility
GAdityaVarma Jan 9, 2026
2a55bbb
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
e1358eb
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
f30fed0
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
3f65074
Improve TruffleHog scan workflow and update docs
GAdityaVarma Jan 9, 2026
467594b
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
693b2e7
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
8770dab
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
1a61036
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
aa00512
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
d57e46b
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
0bff560
Update trufflehog-scan.yml
GAdityaVarma Jan 9, 2026
cbfc2c8
Update trufflehog_readme.md
GAdityaVarma Jan 9, 2026
f610f23
Update trufflehog_readme.md
GAdityaVarma Jan 9, 2026
47a4ca6
PDP-684: updated the workflow for updating the pullrequest comment
brijeshp56 Jan 12, 2026
7ad1df9
PDP-684: Updated to update the comment
brijeshp56 Jan 12, 2026
0666566
PDP-684: Update the existing pull request comment if secrets are reso…
brijeshp56 Jan 13, 2026
06a1ac7
PDP-684: Updated workflow to make sure to scan renamed files
brijeshp56 Jan 14, 2026
518c5d2
Merge branch 'agottumu_dev' into brijesh-dev
brijeshp56 Jan 14, 2026
41f9c2d
Merge pull request #19 from marklogic/brijesh-dev
brijeshp56 Jan 14, 2026
e7e2b95
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 14, 2026
38832a6
Merge pull request #20 from marklogic/brijesh-dev
brijeshp56 Jan 14, 2026
09da209
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 14, 2026
df754f4
Merge pull request #21 from marklogic/brijesh-dev
brijeshp56 Jan 14, 2026
08e940a
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 14, 2026
7ba41eb
Merge pull request #22 from marklogic/brijesh-dev
brijeshp56 Jan 14, 2026
d385450
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 14, 2026
b9540ef
Merge pull request #23 from marklogic/brijesh-dev
brijeshp56 Jan 14, 2026
34848a0
PDP-684 : Update trufflehog-scan.yml for detecting the renamed files
brijeshp56 Jan 16, 2026
d64d46d
Merge branch 'agottumu_dev' into brijesh-dev-backup
brijeshp56 Jan 16, 2026
6cb4ee6
Merge pull request #25 from marklogic/brijesh-dev-backup
brijeshp56 Jan 16, 2026
a0015e2
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 16, 2026
20049b3
Merge pull request #26 from marklogic/brijesh-dev-backup
brijeshp56 Jan 16, 2026
f4e15b5
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 16, 2026
709c401
Merge pull request #27 from marklogic/brijesh-dev-backup
brijeshp56 Jan 16, 2026
9494c79
PDP-684 : Update trufflehog-scan.yml
brijeshp56 Jan 16, 2026
7cc1131
Merge pull request #28 from marklogic/brijesh-dev-backup
brijeshp56 Jan 16, 2026
0a33191
PDP-684: updated workflow to checkout only head commit
brijeshp56 Jan 19, 2026
e6fa7a0
Merge branch 'agottumu_dev' into brijesh-dev
brijeshp56 Jan 19, 2026
74e685b
Merge pull request #29 from marklogic/brijesh-dev
brijeshp56 Jan 19, 2026
d653ce8
PDP-684: updated workflow to checkout only head commit1
brijeshp56 Jan 19, 2026
2029065
Merge branch 'brijesh-dev' of https://github.com/marklogic/pr-workflo…
brijeshp56 Jan 19, 2026
46305c1
Merge pull request #30 from marklogic/brijesh-dev
brijeshp56 Jan 19, 2026
a7b8ecd
PDP-684 : Reverting my changes for trufflehog
brijeshp56 Jan 19, 2026
4f60581
Merge pull request #31 from marklogic/brijesh-dev
brijeshp56 Jan 19, 2026
f21206b
Update trufflehog-scan.yml
GAdityaVarma Jan 22, 2026
1be8f21
Improve secret scan comment update logic
GAdityaVarma Jan 29, 2026
99b8e96
Update trufflehog-scan.yml
GAdityaVarma Jan 29, 2026
c395591
Update trufflehog-scan.yml
GAdityaVarma Jan 30, 2026
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
299 changes: 299 additions & 0 deletions .github/workflows/trufflehog-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
name: TruffleHog Secret Scan

on:
pull_request_target:
types: [opened, synchronize, reopened]
workflow_dispatch:

permissions:
contents: read
pull-requests: write

# Default exclusion patterns (regex format)
# Supports: exact filenames, wildcards, regex patterns
# Examples:
# Exact file: ^config/settings\.json$
# Directory: ^node_modules/
# Extension: \.lock$
# Wildcard: .*\.min\.js$
# Regex: ^src/test/.*_test\.py$

env:
DEFAULT_EXCLUDES: |
^node_modules/
^vendor/
^\.git/
\.lock$
^package-lock\.json$
^yarn\.lock$
^pnpm-lock\.yaml$
\.min\.js$
\.min\.css$

jobs:
trufflehog-scan:
name: Scan PR for Secrets
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fetch PR head commits
if: github.event_name != 'workflow_dispatch'
run: |
# Fetch PR commits using GitHub's merge ref (works for all PRs including forks)
git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head:refs/remotes/origin/pr-head
echo "Fetched PR #${{ github.event.pull_request.number }} head commit: ${{ github.event.pull_request.head.sha }}"

- name: Setup exclude config
id: config
run: |
# Always include default exclusions
echo "Adding default exclusions"
cat << 'EOF' > .trufflehog-ignore
${{ env.DEFAULT_EXCLUDES }}
EOF

# Append repo/org-level custom exclusions if defined
if [ -n "${{ vars.TRUFFLEHOG_EXCLUDES }}" ]; then
echo "Adding repo/org-level TRUFFLEHOG_EXCLUDES patterns"
# Support both comma-separated and newline-separated patterns
echo "${{ vars.TRUFFLEHOG_EXCLUDES }}" | tr ',' '\n' | sed '/^$/d' >> .trufflehog-ignore
fi

echo "Exclusion patterns:"
cat .trufflehog-ignore
echo "exclude_args=--exclude-paths=.trufflehog-ignore" >> $GITHUB_OUTPUT

- name: TruffleHog Scan
id: trufflehog
uses: trufflesecurity/trufflehog@main
continue-on-error: true
with:
base: ${{ github.event.pull_request.base.sha }}
head: ${{ github.event.pull_request.head.sha }}
extra_args: --json ${{ steps.config.outputs.exclude_args }}

- name: Parse scan results
id: parse
if: github.event_name != 'workflow_dispatch'
run: |
# Scan the current state of PR files (not git history)
# This ensures renamed files and removed secrets are handled correctly
echo "Parsing TruffleHog results..."

VERIFIED_COUNT=0
UNVERIFIED_COUNT=0

# Checkout PR head to scan current file state
git checkout ${{ github.event.pull_request.head.sha }} --quiet

# Get list of files changed in this PR (with rename detection)
# -M enables rename detection, showing only the new filename for renamed files
# --diff-filter=d excludes deleted files (we only want files that exist in the PR head)
CHANGED_FILES=$(git diff --name-only -M --diff-filter=d ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }} | grep -v '^$' || true)

if [ -z "$CHANGED_FILES" ]; then
echo "No files changed in PR"
echo "verified_count=0" >> $GITHUB_OUTPUT
echo "unverified_count=0" >> $GITHUB_OUTPUT
exit 0
fi

echo "Scanning changed files:"
echo "$CHANGED_FILES"

# Scan only the changed files in their current state using filesystem scanner
SCAN_OUTPUT=$(docker run --rm -v "$(pwd)":/tmp -w /tmp \
ghcr.io/trufflesecurity/trufflehog:latest \
filesystem /tmp/ \
--json \
${{ steps.config.outputs.exclude_args }} \
--no-update 2>/dev/null || true)

# Parse JSON lines and filter to only changed files
if [ -n "$SCAN_OUTPUT" ]; then
while IFS= read -r line; do
# Skip non-JSON lines (info logs)
if ! echo "$line" | jq -e '.DetectorName' > /dev/null 2>&1; then
continue
fi

FILE=$(echo "$line" | jq -r '.SourceMetadata.Data.Filesystem.file // "unknown"')
# Remove /tmp/ prefix if present
FILE="${FILE#/tmp/}"

# Only count secrets in files that are part of this PR
if ! echo "$CHANGED_FILES" | grep -qx "$FILE"; then
continue
fi

LINE_NUM=$(echo "$line" | jq -r '.SourceMetadata.Data.Filesystem.line // 1')
DETECTOR=$(echo "$line" | jq -r '.DetectorName // "Secret"')
VERIFIED=$(echo "$line" | jq -r '.Verified // false')

if [ "$VERIFIED" == "true" ]; then
VERIFIED_COUNT=$((VERIFIED_COUNT + 1))
# Error annotation for verified secrets
echo "::error file=${FILE},line=${LINE_NUM},title=${DETECTOR} [VERIFIED]::VERIFIED ACTIVE CREDENTIAL: ${DETECTOR} found in ${FILE} at line ${LINE_NUM}. This secret is confirmed active. Remove and rotate immediately!"
else
UNVERIFIED_COUNT=$((UNVERIFIED_COUNT + 1))
# Warning annotation for unverified secrets
echo "::warning file=${FILE},line=${LINE_NUM},title=${DETECTOR} [Unverified]::Potential secret: ${DETECTOR} found in ${FILE} at line ${LINE_NUM}. Review and remove if this is a real credential."
fi
done <<< "$SCAN_OUTPUT"
fi

echo "verified_count=${VERIFIED_COUNT}" >> $GITHUB_OUTPUT
echo "unverified_count=${UNVERIFIED_COUNT}" >> $GITHUB_OUTPUT
echo "Scan complete: ${VERIFIED_COUNT} verified, ${UNVERIFIED_COUNT} unverified secrets found"

- name: Process scan results
id: process
if: github.event_name != 'workflow_dispatch'
run: |
VERIFIED=${{ steps.parse.outputs.verified_count || 0 }}
UNVERIFIED=${{ steps.parse.outputs.unverified_count || 0 }}

if [ "$VERIFIED" -gt 0 ]; then
# Verified secrets found - must fail
echo "has_verified=true" >> $GITHUB_OUTPUT
echo "has_secrets=true" >> $GITHUB_OUTPUT
echo "description=Found ${VERIFIED} verified (active) secrets - action required" >> $GITHUB_OUTPUT
elif [ "$UNVERIFIED" -gt 0 ]; then
# Only unverified secrets - warn but pass
echo "has_verified=false" >> $GITHUB_OUTPUT
echo "has_secrets=true" >> $GITHUB_OUTPUT
echo "description=Found ${UNVERIFIED} unverified potential secrets - review recommended" >> $GITHUB_OUTPUT
else
# No secrets
echo "has_verified=false" >> $GITHUB_OUTPUT
echo "has_secrets=false" >> $GITHUB_OUTPUT
echo "description=No secrets detected in PR changes" >> $GITHUB_OUTPUT
fi

- name: Post PR comment on findings
if: github.event_name != 'workflow_dispatch'
uses: actions/github-script@v7
with:
script: |
const commentMarker = '<!-- TRUFFLEHOG-SCAN-COMMENT -->';
const commitSha = '${{ github.event.pull_request.head.sha }}';
const shortSha = commitSha.substring(0, 7);
const hasSecrets = '${{ steps.process.outputs.has_secrets }}' === 'true';
const hasVerified = '${{ steps.process.outputs.has_verified }}' === 'true';
const verifiedCount = '${{ steps.parse.outputs.verified_count }}' || '0';
const unverifiedCount = '${{ steps.parse.outputs.unverified_count }}' || '0';

// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
per_page: 100
});

const existing = comments.find(c => c.body && c.body.includes(commentMarker));

let body;
if (!hasSecrets) {
// No secrets found
if (existing) {
// Check if existing comment already shows "Passed" state
const alreadyPassed = existing.body.includes(':white_check_mark: Secret Scanning Passed');

if (!alreadyPassed) {
// Update to show all secrets are now resolved
// Determine what type of secrets were previously found
const hadVerified = existing.body.includes('CRITICAL') || existing.body.includes(':rotating_light:');
const previousType = hadVerified ? 'verified secrets' : 'potential secrets';

body = `${commentMarker}
## :white_check_mark: Secret Scanning Passed

**No secrets detected in this pull request.**

**Scanned commit:** \`${shortSha}\` ([${commitSha}](${{ github.server_url }}/${{ github.repository }}/commit/${commitSha}))

Previous ${previousType} have been resolved. Thank you for addressing the security concerns!

---
*This comment will be updated if new secrets are detected in future commits.*
`;
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body: body
});
}
}
// If no existing comment and no secrets, don't post anything
return;
}

// Secrets found - create or update warning comment
let severity, icon, action;
if (hasVerified) {
severity = 'CRITICAL';
icon = ':rotating_light:';
action = 'This PR is **blocked** until verified secrets are removed.';
} else {
severity = 'Warning';
icon = ':warning:';
action = 'This PR can proceed, but please review the potential secrets below.';
}

body = `${commentMarker}
## ${icon} Secret Scanning ${severity}

**TruffleHog scan results:**
- **Verified (active) secrets:** ${verifiedCount} ${verifiedCount > 0 ? ':x:' : ':white_check_mark:'}
- **Unverified (potential) secrets:** ${unverifiedCount} ${unverifiedCount > 0 ? ':warning:' : ':white_check_mark:'}

**Scanned commit:** \`${shortSha}\` ([${commitSha}](${{ github.server_url }}/${{ github.repository }}/commit/${commitSha}))

${action}

### What to do:
1. **Review the workflow annotations** - they point to exact file and line locations
2. **Remove any exposed secrets** from your code
3. **Rotate compromised credentials** - especially verified ones
4. **Push the fix** to this branch

### Understanding Results
| Type | Meaning | Action Required |
|------|---------|-----------------|
| **Verified** | Confirmed active credential | **Must remove & rotate** - PR blocked |
| **Unverified** | Potential secret pattern | Review recommended - PR can proceed |

Check the [workflow run logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.

---
*Verified secrets are confirmed active by TruffleHog. Unverified secrets match known patterns but couldn't be validated.*
`;

if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: body
});
}

- name: Fail workflow if verified secrets found
if: steps.process.outputs.has_verified == 'true'
run: |
echo "::error::VERIFIED SECRETS DETECTED - These are confirmed active credentials that must be removed and rotated immediately."
exit 1
Loading