Skip to content

fix: stop disabling TruffleHog verification for verified-only scans - #110

Open
lelia wants to merge 4 commits into
mainfrom
lelia/ce-351-fix-trufflehog-verified-only-behavior-and-clarify-exclude
Open

fix: stop disabling TruffleHog verification for verified-only scans#110
lelia wants to merge 4 commits into
mainfrom
lelia/ce-351-fix-trufflehog-verified-only-behavior-and-clarify-exclude

Conversation

@lelia

@lelia lelia commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Stabilizes the TruffleHog experience further (building off #94) for a single upcoming release.

1. Verification always runs, while result filtering stays configurable

Turning Show Unverified Secrets off passed --no-verification, which disabled verification outright instead of filtering the returned findings.

Severity is derived from each finding's Verified flag, so disabling verification made every finding Verified: falselow → non-blocking. On the setting's default path, no secret could ever block a run—the inverse of the intended behavior.

Verification now always runs, and the setting selects result types only:

trufflehog_show_unverified TruffleHog flag Socket behavior
off (default) --results=verified,unknown Verified findings are critical/blocking; verification failures remain visible as low/non-blocking unknown findings
on --results=verified,unverified,unknown Also includes candidates that were checked but not confirmed as valid, as low/non-blocking findings

Keeping unknown in the default result set is deliberate. TruffleHog uses that state when verification cannot complete because of a network or API error; dropping it would let an air-gapped or broken-verification run appear clean. Alerts now expose props.verificationStatus (verified, unknown, or unverified) and the detailed report no longer labels unknown as a negative verification result.

--include-detectors=all is passed unconditionally so detector selection no longer changes as a side effect of the setting. TruffleHog already defaults to all detectors, so this is a no-op in practice.

Boolean values are read through coerce_bool for trufflehog_show_unverified, secret_scanning_enabled, and the TruffleHog scan_all fallback. The environment loader produces booleans, but dashboard/JSON configuration can supply strings at higher priority; values such as "false" must not enable scanning, include unverified findings, or widen a staged-file scan.

2. A TruffleHog run that cannot complete no longer looks clean

The wrapper previously logged any non-zero exit and converted it into an empty result. A malformed exclude pattern, broken installation, or other execution error could therefore zero out secret findings while the workflow exited green.

The command now passes --fail-on-scan-errors, which makes TruffleHog return non-zero for source and enumeration errors that it otherwise only logs. The wrapper fails the run on that non-zero exit and when the trufflehog binary is missing, including the exit code and TruffleHog stderr in the error.

SystemExit is deliberate: the connector manager catches Exception, so an ordinary connector exception would be downgraded to a skipped connector and the run would still appear successful. The exclude-file cleanup in the finally block still runs on this path.

Behavioral changes on upgrade

  1. Verified secrets can start blocking runs that previously passed. Those findings were previously forced to low severity because verification was disabled; verified findings are now critical and blocking as intended.
  2. TruffleHog makes outbound validation requests. Verification checks candidates against provider endpoints such as AWS, GitHub, and Slack.
  3. Verification outages remain visible. Air-gapped, proxied, or temporarily failing validation requests produce unknown findings by default. They are low severity and non-blocking, but the scan no longer silently reports zero findings solely because validation could not complete.
  4. Scanner execution errors fail the run. A missing binary, malformed arguments, source/enumeration failure, or other non-zero TruffleHog exit no longer becomes an empty clean result.

These choices favor transparent, fail-closed secret scanning while reserving blocking behavior for credentials TruffleHog confirms are live.

Validation

  • uv run --with pytest pytest -q353 passed
  • Verified against the pinned trufflesecurity/trufflehog:3.96.0 binary:
    • An offline AWS candidate returned Verified: false plus VerificationError under --results=unknown, confirming the status signal used by the alert mapping.
    • A missing filesystem target scanned zero bytes and exited 0 without --fail-on-scan-errors; the same command exited 1 with the flag.
    • A throwaway RSA private key was returned by --results=verified,unverified,unknown and omitted by the old verified-only filter.
  • Confirmed --no-verification is absent in both setting states and detector selection is identical.
  • Smoke-tested module compilation and checked the patch with git diff --check.

tests/test_trufflehog_verification.py now covers both result-filter states, unknown/unverified/verified alert mapping, string boolean forms, the disabled-scanner path, staged-file fallback with string "false", the scan-error flag, non-zero exits, and a missing binary.

Docs

Updated docs/parameters.md, docs/github-action.md, action.yml, and connectors.yaml to explain:

  • verification always runs and requires network egress;
  • verified and unknown results are returned by default;
  • only verified findings block;
  • trufflehog_show_unverified adds definitively unverified candidates; and
  • trufflehog_exclude_dir accepts directory names, file names, and glob patterns.

Also corrected the JSON configuration example from the nonexistent show_unverified key to trufflehog_show_unverified.

Fixes CE-351
Fixes CE-347

Turning trufflehog_show_unverified off passed --no-verification, which
disabled verification outright instead of returning only verified findings.
Severity is derived from each finding's Verified flag, so every result came
back Verified: false -> low severity -> non-blocking. On the setting's
default path no secret could ever block a run: the exact inverse of intent.

Verification now always runs, and the setting selects result types only:
--results=verified when off, --results=verified,unverified,unknown when on
(the latter matching TruffleHog's own default). Verified findings stay
critical/blocking, unverified stay low/non-blocking.

--include-detectors=all is now passed unconditionally so detector selection
no longer changes as a side effect of the setting. TruffleHog already
defaults to all detectors, so this is a no-op in practice.

Verified against the pinned trufflesecurity/trufflehog:3.96.0 binary: an
unverifiable private key is returned under the "on" filter and dropped under
the "off" filter.

Two upgrade consequences, documented in the changelog: runs with the setting
off will start reporting blocking critical findings previously downgraded to
low, and verification is a live check, so TruffleHog now makes outbound
requests to third-party credential-validation endpoints.

Also corrects TruffleHog parameter docs (exclude paths accept files and
globs, not just directories; show-unverified widens result types rather than
toggling verification) and a JSON config example that named a nonexistent
show_unverified key.

Fixes CE-351

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lelia
lelia requested a review from a team as a code owner September 3, 2026 18:21
Comment thread socket_basics/core/connector/trufflehog/__init__.py
lelia and others added 2 commits September 3, 2026 14:55
Only the environment loader coerces bool params (config.py:924). A Socket
dashboard config is passed through verbatim (config.py:1309) and outranks
env, so a dashboard-supplied string "false" reached the connector as a
truthy value.

Under the old --no-verification code that misread was a harmless no-op: it
selected --include-detectors=all, which is TruffleHog's default anyway. Now
it would select --results=verified,unverified,unknown and report unverified
secrets to someone who explicitly asked for verified-only, so the same latent
misread became a real behavioral bug.

Covers "false"/"False"/"0"/"no", the true forms, and the unset cases (None
and the empty string an unset action input forwards). Verified the new test
fails against the truthiness read and passes with coerce_bool.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Any non-zero exit was logged and converted into an empty result, so a
malformed exclude pattern or a broken install silently zeroed out every
secret finding while the run exited green. A scanner that could not scan
looked identical to a repository with no secrets.

Non-zero exits and a missing trufflehog binary now raise SystemExit with the
exit code and TruffleHog's own stderr. SystemExit is deliberate: the
connector manager catches Exception, and this must not be downgraded to a
skipped connector. The exclude-file cleanup in the finally block still runs
on the failure path.

This closes the last open acceptance criterion from CE-347 ("a
malformed/unopenable exclude value no longer causes trufflehog to silently
return zero findings for the whole run"). Its other two criteria shipped in
2.2.1 via #94, which referenced CE-347 without closing it.

Matches the fail-closed idiom already used for an unresolvable changed_files
scope, which also raises SystemExit with an actionable message.

test_scan_cleans_exclude_file_when_trufflehog_fails asserted the old
swallowing behavior; it now expects the failure to surface while still
asserting the temp filter file is cleaned up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lelia

lelia commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 64cf028. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant