feat: add Rancher/Cattle token detector#4997
Conversation
Implements a TruffleHog detector for Rancher Kubernetes management platform API tokens (CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD, RANCHER_API_TOKEN). Pattern: 54–64 lowercase alphanumeric chars prefixed by a named cattle/rancher variable (reduces false positives from the broad character set). Validation hits the /v3 endpoint with a Bearer header when a CATTLE_SERVER/RANCHER_URL is found in the same chunk. Closes trufflesecurity#4622
|
|
||
| req, err := http.NewRequestWithContext(ctx, "GET", serverURL+"/v3", nil) | ||
| if err != nil { | ||
| continue |
There was a problem hiding this comment.
continue silently drops detected secrets during verification failure
High Severity
When http.NewRequestWithContext returns an error (e.g., due to a malformed server URL), the continue statement skips the results = append(results, s1) on line 69. This causes a legitimately detected secret to be silently dropped instead of being reported as an unverified finding. Every other multi-part detector in this codebase (e.g., databrickstoken, grafana) always appends the result regardless of verification outcome.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit ffc2490. Configure here.
|
|
||
| res, err := client.Do(req) | ||
| if err == nil { | ||
| defer func() { _ = res.Body.Close() }() |
There was a problem hiding this comment.
defer inside loop delays response body cleanup
Medium Severity
The defer res.Body.Close() is inside the for loop, so response bodies accumulate and are only closed when FromData returns rather than after each iteration. Every comparable detector in this codebase extracts verification into a separate function where defer executes promptly upon that function's return. With multiple token matches, this leaks open connections during the loop.
Reviewed by Cursor Bugbot for commit ffc2490. Configure here.
| var _ detectors.Detector = (*Scanner)(nil) | ||
|
|
||
| var ( | ||
| client = common.SaneHttpClient() |
There was a problem hiding this comment.
SSRF risk: unconstrained URL with permissive HTTP client
Medium Severity
The detector uses common.SaneHttpClient() which lacks local/private IP blocking, but the serverPat regex accepts any https?:// URL from scanned data. Other detectors with unconstrained user-supplied URLs (like artifactory and jiradatacenterpat) specifically use detectors.DetectorHttpClientWithNoLocalAddresses to prevent SSRF. An attacker could embed CATTLE_SERVER=http://169.254.169.254 in scanned content to trigger requests to cloud metadata endpoints during verification.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit ffc2490. Configure here.
- Use DetectorHttpClientWithNoLocalAddresses to prevent SSRF via attacker-controlled CATTLE_SERVER values - Extract verification into verifyToken() helper so defer executes promptly after each call, not when FromData returns - Always append result even when request creation fails; only s1.Verified stays false, matching other detector conventions
| client = detectors.DetectorHttpClientWithNoLocalAddresses | ||
|
|
||
| // Rancher API tokens: 54–64 lowercase alphanumeric chars, named with cattle/rancher prefixes. | ||
| keyPat = regexp.MustCompile(`(?i)(?:CATTLE_TOKEN|RANCHER_TOKEN|CATTLE_BOOTSTRAP_PASSWORD|RANCHER_API_TOKEN)[\w]*\s*[=:]\s*["']?([a-z0-9]{54,64})["']?`) |
There was a problem hiding this comment.
Case-insensitive flag broadens token matching unintentionally
Medium Severity
The (?i) flag at the start of keyPat applies to the entire regex, including the token capture group [a-z0-9]{54,64}. In RE2, (?i) causes [a-z] to also match uppercase letters, so the capture group effectively becomes [a-zA-Z0-9]{54,64}. This contradicts the PR's stated intent of matching only "lowercase alphanumeric characters" and weakens the false-positive suppression the narrow character class was meant to provide. The (?i) flag is needed for case-insensitive variable name matching, but it needs to be scoped (e.g., via (?i:...)) so it doesn't affect the token capture group.
Reviewed by Cursor Bugbot for commit 9bf0780. Configure here.
| "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/sonarcloud" | ||
| "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/sourcegraph" | ||
| "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/sourcegraphcody" | ||
| "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rancher" |
There was a problem hiding this comment.
Import and registration placed out of alphabetical order
Low Severity
The rancher import and &rancher.Scanner{} registration are placed between sourcegraphcody and spectralops (in the 's' section) instead of in the 'r' section between ramp and rapidapi where they belong alphabetically. All other detectors in this file follow strict alphabetical ordering.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 9bf0780. Configure here.
… order
- keyPat: use (?i:...) to apply case-insensitivity only to the variable
name prefix (CATTLE_TOKEN etc.), leaving the token capture group
[a-z0-9]{54,64} strictly lowercase as intended
- defaults.go: move rancher import and Scanner{} registration to
alphabetical position between ramp and rapidapi
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 6 total unresolved issues (including 5 from previous reviews).
Reviewed by Cursor Bugbot for commit df672a6. Configure here.
| } | ||
| defer func() { _ = res.Body.Close() }() | ||
| return res.StatusCode == http.StatusOK | ||
| } |
There was a problem hiding this comment.
Verification errors silently swallowed, misclassifying results
Medium Severity
verifyToken returns only bool, swallowing all errors (network timeouts, DNS failures, non-200 status codes). Because SetVerificationError is never called, the engine at engine.go:1274 misclassifies transient verification failures as definitively "unverified" instead of "unknown." Users filtering with --results=verified,unknown will silently miss these results. The established pattern (seen in apiflash.go, abstract.go, and most other detectors) is to return (bool, error) and call s1.SetVerificationError(...).
Additional Locations (1)
Reviewed by Cursor Bugbot for commit df672a6. Configure here.
Return (bool, error) from verifyToken so transient failures (network timeouts, DNS errors) are reported via s1.SetVerificationError instead of being silently swallowed. This lets the engine classify results as 'verification error' rather than 'unverified', consistent with the rest of the detector codebase (apiflash, abstract, etc).
|
All 6 issues from Cursor Bugbot reviews are now resolved:
|


Summary
Adds a detector for Rancher Kubernetes management platform API tokens, as requested in #4622.
Token pattern
Rancher tokens are 54–64 lowercase alphanumeric characters, always assigned to named variables:
The regex anchors on the variable name prefix (CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD, RANCHER_API_TOKEN) to suppress false positives from the broad
[a-z0-9]character class.Validation
When CATTLE_SERVER or RANCHER_URL is found in the same chunk, the detector hits
GET {server}/v3withAuthorization: Bearer {token}. HTTP 200 → verified.Changes
pkg/detectors/rancher/rancher.go— detector implementationpkg/detectors/rancher/rancher_test.go— pattern tests (no live calls)proto/detector_type.proto—RancherToken = 1053pkg/pb/detector_typepb/detector_type.pb.go— updated generated mapspkg/engine/defaults/defaults.go— registeredrancher.Scanner{}Closes #4622
Note
Low Risk
Isolated new detector following existing SSRF-safe verification patterns; no changes to core scan or auth paths.
Overview
Adds Rancher / Cattle API token detection for TruffleHog, including a new
RancherTokendetector type (1053) wired into the default engine.The scanner finds 54–64 character lowercase alphanumeric tokens only when they appear next to known env-style names (
CATTLE_TOKEN,RANCHER_TOKEN,CATTLE_BOOTSTRAP_PASSWORD,RANCHER_API_TOKEN). When verification is enabled and a server URL is present in the same chunk (CATTLE_SERVER,RANCHER_URL,RANCHER_SERVER), it checks credentials withGET {server}/v3and a Bearer token, using the SSRF-safe HTTP client used by other detectors.Pattern-only tests cover a positive
CATTLE_TOKENcase and a negative case without Rancher variable names (no live HTTP).Reviewed by Cursor Bugbot for commit 19490ee. Bugbot is set up for automated code reviews on this repo. Configure here.