Skip to content

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

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

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

Conversation

@toor11
Copy link
Copy Markdown

@toor11 toor11 commented May 12, 2026

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
Low risk, mostly additive: introduces a new secret detector and registers it in defaults, plus a protobuf enum addition. Main risk is limited to potential false positives/negatives or downstream consumers needing to recognize the new DetectorType_Rancher value.

Overview
Adds a new rancher detector that finds Rancher/Cattle tokens by anchoring to known env var prefixes and extracting 54–64 char lowercase token values, returning results as unverified (no live verification).

Registers the new scanner in the default detector list and extends DetectorType with a new Rancher = 1050 enum value (updating both proto/detector_type.proto and the generated detector_type.pb.go). Includes unit tests covering expected matches and common non-matches (quoted values, missing context, uppercase tokens, invalid length).

Reviewed by Cursor Bugbot for commit 5c0ee37. 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 a review from a team May 12, 2026 14:32
@toor11 toor11 requested review from a team as code owners May 12, 2026 14:32
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 12, 2026

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
// to avoid false positives on generic random strings.
keyPat = regexp.MustCompile(
`(?i)(?:CATTLE_TOKEN|RANCHER_TOKEN|CATTLE_BOOTSTRAP_PASSWORD|RANCHER_API_TOKEN|RANCHER_SECRET_KEY)` +
`[\w]*\s*[=:]\s*["']?([a-z0-9]{54,64})["']?`)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing boundary allows matching prefix of longer strings

Medium Severity

The regex lacks a word boundary (\b) after the token capture group ([a-z0-9]{54,64}). Because ["']? is optional and always succeeds, a value longer than 64 alphanumeric characters (e.g., a long hash or concatenated string) will have its first 64 characters silently captured as a "token," producing a false positive with a truncated value. The azure_storage detector avoids this by using \b([a-z0-9]{3,24})\b.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 99e8e27. Configure here.

…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.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

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
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/qubole"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rabbitmq"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/railwayapp"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rancher"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Import and registration break alphabetical ordering convention

Low Severity

The rancher import and scanner registration are inserted before ramp, breaking the alphabetical ordering maintained throughout defaults.go. Alphabetically, ramp (r-a-m) precedes rancher (r-a-n), so the new entry belongs after ramp and before rapidapi. This inconsistency increases the risk of merge conflicts with other PRs adding detectors nearby.

Additional Locations (1)
Fix in Cursor Fix in Web

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

…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.

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