Skip to content

feat(detectors): add BcryptHash detector#5055

Open
deerajcm wants to merge 1 commit into
trufflesecurity:mainfrom
deerajcm:add-bcrypt-hash-detector
Open

feat(detectors): add BcryptHash detector#5055
deerajcm wants to merge 1 commit into
trufflesecurity:mainfrom
deerajcm:add-bcrypt-hash-detector

Conversation

@deerajcm

@deerajcm deerajcm commented Jun 19, 2026

Copy link
Copy Markdown

Summary

  • Adds a detector for bcrypt password hashes found in code
  • Detects all bcrypt variants: $2a$, $2b$, and $2y$
  • Pattern-only detection - no verification (bcrypt is a one-way hash)
  • Adds BcryptHash = 1055 to proto/detector_type.proto, regenerated pb.go, and registers the scanner in pkg/engine/defaults/defaults.go
  • Populates SecretParts with the hash value

Test plan

  • go test ./pkg/detectors/bcrypthash -tags=detectors -v — all 9 test cases pass
  • go build ./... succeeds
  • go vet ./... clean
  • Manual testing with trufflehog binary - detected 3/3 valid bcrypt hashes, 0 false positives

Notes

Bcrypt hashes found in code may indicate leaked password hashes. While bcrypt is a secure one-way hashing algorithm, exposed hashes can be targeted by attackers for offline cracking attempts.

Detection

  • Keyword pre-filter: $2a$, $2b$, $2y$, bcrypt
  • Pattern: \$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}\b
  • Matches all three bcrypt variants with proper cost factor and hash length

No Verification
Bcrypt hashes are one-way cryptographic hashes and cannot be verified without the original password. Results are detected but not verified (consistent with other pattern-only detectors like JWT).


Note

Low Risk
Isolated new detector plus enum/proto registration; no changes to auth, verification, or core scan pipeline beyond one more default scanner.

Overview
Adds a BcryptHash scanner so TruffleHog can flag bcrypt password hashes ($2a$, $2b$, $2y$) in scanned content.

The new detector uses keyword pre-filtering and a strict regex for cost + 53-character salt/hash payload, deduplicates matches, emits unverified findings with SecretParts["hash"], and applies the shared DefaultFalsePositives check via IsFalsePositive. There is no remote verification (one-way hashes).

Wiring includes BcryptHash = 1055 in proto/detector_type.proto with regenerated detector_type.pb.go, registration of bcrypthash.Scanner in pkg/engine/defaults/defaults.go, and unit tests for valid/invalid patterns and FromData behavior.

Reviewed by Cursor Bugbot for commit f2fefc5. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds a detector for bcrypt password hashes found in code.
Detects bcrypt hash formats: $2a$, $2b$, and $2y$ variants.
No verification is performed as bcrypt is a one-way hash.

- Adds DetectorType_BcryptHash (enum 1055) to proto
- Implements Scanner with pattern matching for bcrypt hashes
- Includes comprehensive tests for all bcrypt variants
- Registers detector in DefaultDetectors

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@deerajcm deerajcm requested a review from a team June 19, 2026 07:46
@deerajcm deerajcm requested review from a team as code owners June 19, 2026 07:46
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Deeraj CM seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit f2fefc5. Configure here.

var (
// Bcrypt hash format: $2a$, $2b$, or $2y$ followed by cost (2 digits) and 53 base64 chars
// Example: $2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
bcryptPat = regexp.MustCompile(`\$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}\b`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Regex \b boundary misses hashes ending in .

High Severity

The \b word boundary at the end of bcryptPat fails to match valid bcrypt hashes whose 53rd character is . or /, since those are non-word characters. When followed by another non-word character (quote, space, newline, end-of-string), no word boundary exists and the regex won't match. Due to bcrypt's modified base64 encoding, . is one of only four possible values for the last hash character, meaning roughly 25% of valid bcrypt hashes go undetected in typical code contexts like quoted strings.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f2fefc5. Configure here.


func (s Scanner) IsFalsePositive(result detectors.Result) (bool, string) {
return detectors.IsKnownFalsePositive(string(result.Raw), detectors.DefaultFalsePositives, true)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

False positive checker incorrectly filters valid bcrypt hashes

High Severity

The IsFalsePositive method runs the default word-list check (IsKnownFalsePositive with wordCheck=true) against the raw bcrypt hash. Since bcrypt hashes are 53+ characters of pseudo-random base64, they very likely contain common English substrings (e.g., "from", "name", "data", "type") from the false-positive word lists, causing legitimate hashes to be silently dropped. Every other CustomFalsePositiveChecker in the codebase returns false, "" to bypass this check — this implementation needs to do the same.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f2fefc5. 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.

2 participants