GitHub Action: unhandled event types silently fall through to a full-history scan (BASE/HEAD left empty)
Summary
The action's event dispatch has branches for push, workflow_dispatch/schedule, and pull_request. Any other github.event_name falls out of the ladder with BASE and HEAD still unset, and the scan then runs with empty --since-commit and --branch. Combined with the fetch-depth: 0 checkout the action's own README recommends, the effect is a silent full-history scan across all fetched refs — where the user expected a diff scan, and with no indication in the log that the scope changed.
release is the case that bit us, but the same applies to merge_group, pull_request_target, push_tag, and anything else not in the list.
The code
action.yml:
else
if [ "${{ github.event_name }}" == "push" ]; then
...
elif [ "${{ github.event_name }}" == "workflow_dispatch" ] || [ "${{ github.event_name }}" == "schedule" ]; then
BASE=""
HEAD=""
elif [ "${{ github.event_name }}" == "pull_request" ]; then
BASE=${{github.event.pull_request.base.sha}}
HEAD=${{github.event.pull_request.head.sha}}
fi
fi
...
docker run --rm -v .:/tmp -w /tmp \
"${IMAGE}:${VERSION}" \
git file:///tmp/ \
--since-commit \
${BASE:-''} \
--branch \
${HEAD:-''} \There is no else on the inner ladder. For an unhandled event both variables stay empty and ${BASE:-''} / ${HEAD:-''} expand to empty strings.
Worth contrasting with the guard immediately above it, which handles the opposite failure explicitly:
## If BASE == HEAD, exit with error
echo "::error::BASE and HEAD commits are the same. TruffleHog won't scan anything. Please see documentation (...)""Scans nothing" gets a hard error. "Scans everything, on every ref, unasked" gets nothing.
Observed
A release: [published] run, on a workflow whose other jobs are shared with its PR checks:
if [ "release" == "push" ]; then ...
elif [ "release" == "workflow_dispatch" ] || [ "release" == "schedule" ]; then ...
elif [ "release" == "pull_request" ]; then ...
fi
env:
BASE:
HEAD:scanning repo {"unit": "/tmp/trufflehog-19-2005203197", "repo": "file:///tmp"}
finished scanning {"chunks": 5730, "bytes": 3110451, "verified_secrets": 20, ...}
##[error]Process completed with exit code 1835730 chunks is the entire history, not the release diff.
Why this is worse than a scope surprise
The findings a history scan surfaces are, by construction, things you cannot fix by changing code — they're immutable commits. So the failure is not actionable in the way a diff finding is, and it arrives at release time rather than at review time.
In our case all 20 were false positives from the Lob detector (#5184), the oldest from 2024. The PR that introduced each of those filenames had passed, correctly, because PR runs scan a diff. The same commits then blocked a release two years later. Two defects were needed to produce that outcome, and this is the one that decided when it landed and how much it surfaced.
It also makes the behaviour non-obvious to debug: identical code, identical action ref, one job passes and one fails, and nothing in the log says the scan scope differed.
Suggested fix
Any of these would be an improvement, roughly in order of preference:
- Add an
elsethat fails loudly, mirroring theBASE == HEADguard —::error::naming the unhandledevent_nameand pointing at thebase/headinputs. Unhandled input should not silently become the most expensive possible behaviour. - Handle
releaseexplicitly.github.event.release.tag_nameand the previous tag are both reachable, so a tag-to-tag diff is well defined. - Log the effective scan scope unconditionally — one line stating diff-vs-full and the resolved BASE/HEAD. Cheap, and it would have made this self-diagnosing.
Happy to open a PR for (1) plus (3) if you'd take it.
Environment
- Action
trufflesecurity/[email protected], scanner image3.96.0 actions/checkout@v7withfetch-depth: 0extra_args: --only-verified- Runner
ubuntu-24.04
Source: trufflesecurity/trufflehog