Skip to content

feat(detectors): add Rancher/Cattle token detector - #4960

Open
toor11 wants to merge 8 commits into
trufflesecurity:mainfrom
toor11:feat/rancher-token-detector
Open

feat(detectors): add Rancher/Cattle token detector#4960
toor11 wants to merge 8 commits into
trufflesecurity:mainfrom
toor11:feat/rancher-token-detector

Conversation

@toor11

@toor11 toor11 commented May 12, 2026

Copy link
Copy Markdown

Summary

Closes #4622. Adds a detector for Rancher API tokens (used by the Rancher Kubernetes management platform, deployed at 37,000+ organizations).

Detection Strategy

Tokens are anchored to known Rancher/Cattle variable names to avoid false positives on generic [a-z0-9]{54,64} strings (as flagged in the issue):

CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD, RANCHER_API_TOKEN, RANCHER_SECRET_KEY

Regex pattern:

(?i)(?:CATTLE_TOKEN|RANCHER_TOKEN|CATTLE_BOOTSTRAP_PASSWORD|RANCHER_API_TOKEN|RANCHER_SECRET_KEY)[\w]*\s*[=:]\s*["']?([a-z0-9]{54,64})["']?

Verification

Verification requires a live Rancher server URL (CATTLE_SERVER) which is not available at scan time. Matched tokens are returned as unverified. A future enhancement could extract CATTLE_SERVER from the same context chunk and attempt GET {server}/v3 with Authorization: Bearer {token}.

Changes

  • pkg/detectors/rancher/rancher.go — detector implementation
  • pkg/detectors/rancher/rancher_test.go — pattern tests (env file, quoted values, no-context rejection, length rejection)
  • proto/detector_type.protoRancher = 1050
  • pkg/pb/detector_typepb/detector_type.pb.go — generated enum update
  • pkg/engine/defaults/defaults.go — registered &rancher.Scanner{}

Test Results

ok  github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rancher  0.391s

Note

Low Risk
Additive detector-only change with no auth or scan-engine behavior changes; main review focus is regex false positives/negatives and unverified findings.

Overview
Adds Rancher/Cattle API token detection for secrets commonly set as CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD, RANCHER_API_TOKEN, or RANCHER_SECRET_KEY, paired with a lowercase alphanumeric value 54–64 characters (quoted values and = / : separators supported). Matches are deduplicated and emitted as unverified results—there is no live verification against a Rancher CATTLE_SERVER URL.

Registers the new rancher.Scanner in the default detector list and extends DetectorType_Rancher = 1058 in proto/detector_type.proto and generated protobuf code. rancher_test.go covers env-style assignments, quoted secrets, and negative cases (wrong variable name, bad length, uppercase token, overlong suffix).

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

Detects Rancher API tokens by matching common Rancher/Cattle variable
names (CATTLE_TOKEN, RANCHER_TOKEN, CATTLE_BOOTSTRAP_PASSWORD,
RANCHER_API_TOKEN, RANCHER_SECRET_KEY) followed by a 54-64 char
lowercase alphanumeric token.

Anchoring detection to known variable names avoids false positives on
generic [a-z0-9]{54,64} strings. Verification requires a live Rancher
server URL (CATTLE_SERVER) which is not available at scan time, so
matched tokens are flagged as unverified.

Closes trufflesecurity#4622
@toor11
toor11 requested review from a team May 12, 2026 14:32
@toor11
toor11 requested a review from a team as a code owner May 12, 2026 14:32
@CLAassistant

CLAassistant commented May 12, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread pkg/detectors/rancher/rancher.go Outdated
verifyRancherToken was returning a non-nil error, causing
SetVerificationError to mark every result as unknown instead of
unverified. Tokens were silently dropped unless --results=unknown
was set. Returning (false, nil) correctly classifies them as
unverified.
Comment thread pkg/detectors/rancher/rancher.go Outdated
Comment thread pkg/detectors/rancher/rancher.go Outdated
…re case-sensitive

The global (?i) flag was widening the [a-z0-9]{54,64} capture group to
also match uppercase letters, causing false positives on uppercase strings.
Rancher tokens are lowercase alphanumeric only.

Replace (?i)(?:PREFIX) with (?i:PREFIX) so case-insensitivity applies
only to the variable name prefix, matching the pattern used by
azure_storage and other detectors in the codebase.

Added an uppercase token test case to assert the capture group
remains case-sensitive.

@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 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 5c0ee37. Configure here.

Comment thread pkg/engine/defaults/defaults.go Outdated
…oundary, and ordering

- Add missing context import (was causing build failure)
- Add \b after token capture group to prevent matching first 64 chars
  of tokens longer than 64 chars (false positive on truncated values)
- Drop unused verify scaffolding (net/http, verifyRancherToken, defaultClient)
  so results are correctly classified as unverified, not unknown
- Fix alphabetical ordering of rancher import and registration in defaults.go
  (ramp < rancher)
- Add test case for over-length token rejection
@gugacyber

Copy link
Copy Markdown

Nice work on this detector, the regex scoping of (?i:PREFIX) and the \b boundary fix are exactly right.
One thing worth checking: DetectorType_Rancher = 1050 may conflict with DetectorType_GitLabOauth2 = 1050 which was registered in a recent merge (#4950s range). Worth verifying the enum value against current main.
Also noticed the Scanner struct doesn't implement Description() string, other detectors in the codebase include it (e.g. stripe.go line 83). Not a blocker but keeps things consistent.
Overall the detection logic looks solid. The anchored variable name approach is the right call for a generic-looking token format like this.

…tector

# Conflicts:
#	pkg/pb/detector_typepb/detector_type.pb.go
#	proto/detector_type.proto
@toor11
toor11 requested a review from a team May 28, 2026 21:29
@toor11

toor11 commented May 31, 2026

Copy link
Copy Markdown
Author

Thanks for the careful review, @gugacyber! 🙏 Both of your points are handled:

  • Enum value: Rancher is currently 1053 in detector_type.proto, and I verified there are no duplicate enum values — the generated detector_type.pb.go matches at DetectorType_Rancher = 1053, so there is no collision with GitLabOauth2 = 1050.
  • Description(): implemented on the Scanner struct (pkg/detectors/rancher/rancher.go L58–61), consistent with the other detectors.

The Cursor Bugbot items (scoped (?i:...), the \b boundary, and alphabetical ordering in defaults.go) were addressed in the earlier commits. I think it is ready for another look whenever a maintainer has a moment — thanks again for the thoughtful feedback!

@toor11
toor11 requested a review from a team May 31, 2026 20:17
@toor11 toor11 mentioned this pull request Jun 1, 2026
toor11 added 2 commits June 9, 2026 23:51
…tector

# Conflicts:
#	pkg/pb/detector_typepb/detector_type.pb.go
#	proto/detector_type.proto
@toor11

toor11 commented Jul 9, 2026

Copy link
Copy Markdown
Author

@MuneebUllahKhan222 — apologies for the direct ping, and please redirect me if this isn't yours. This PR (adds the Rancher/Cattle token detector requested in #4622) has been open since May 12 without a reviewer assigned, and I believe it's ready.

Status

  • CLA signed.
  • All four Cursor Bugbot findings addressed: (?i:...) scoped to the variable-name prefix only (token capture stays case-sensitive), \b boundary so a longer string can't match on a truncated 64-char prefix, results returned as unverified (Verified=false, no VerificationError) since there's no live verification path, and import + scanner registration placed alphabetically between ramp and rapidapi.
  • Review feedback from @gugacyber addressed.
  • As of my last rebase (Jul 6), go test ./pkg/detectors/rancher/ and go test ./pkg/engine/defaults/ both passed.

On the conflict

The only thing marking this conflicting is the DetectorType enum value. Since the numbers are handed out next-sequentially, every open detector PR contests the same one, so an unmerged PR can't hold a number: Rancher has already been renumbered twice (1050 → 1053 → 1058), each time displaced by a detector that merged first — most recently NewRelicInsightsInsertKey took 1058 in #4778. It would be 1062 today, and it will drift again the next time a detector lands.

Rather than keep rebasing into a value that's contested by construction, I'd rather do it once, when it actually counts: whenever you're ready to look at this — or just start a review — I'll renumber to the next free value and push straight away so it lands clean.

Happy to make any other changes you'd like.

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.

Rancher Tokens

3 participants