Skip to content

feat(detectors): add RSA SecurID software token detector#5106

Open
momomuchu wants to merge 2 commits into
trufflesecurity:mainfrom
momomuchu:detector-rsasecurid
Open

feat(detectors): add RSA SecurID software token detector#5106
momomuchu wants to merge 2 commits into
trufflesecurity:mainfrom
momomuchu:detector-rsasecurid

Conversation

@momomuchu

@momomuchu momomuchu commented Jul 2, 2026

Copy link
Copy Markdown

Description

Closes #4395.

Adds a detector for RSA SecurID software tokens distributed as .sdtid XML files. Each token export contains a <SN> serial (12 digits) and a <Seed> TOTP seed (128-bit hex, or an AES-encrypted seed in base64). The seed lets an attacker generate valid one-time passcodes and defeat the MFA factor, so both parts are reported as a multi-part credential (serial + seed).

Detection rationale

  • <SN>(\d{12})</SN> and <Seed>([A-Za-z0-9+/]{16,}={0,2})</Seed> must both be present.
  • A structural guard requires an RSA SecurID marker (<TKNBatch>, <TKNBasic>, or .sdtid) before emitting, so generic XML with unrelated <SN>/<Seed> elements is not flagged. This is the primary false-positive defense.
  • No public endpoint can validate a software token, so results are unverified.

Test coverage

8 pattern cases: 2 positive (hex seed, base64/encrypted seed) and 6 negative (SN only, Seed only, wrong element names, short seed, wrong-length serial, missing structural marker). All synthetic/fake values — no real token material.

Note on generated protobuf

proto/detector_type.proto is updated with the new RSASecurID enum, and the generated detector_type.pb.go carries the matching constant + name/value map entries so the package builds and the enum resolves. The embedded descriptor blob was not regenerated (the make protos toolchain runs in a pinned Docker image unavailable in my environment). Running make protos before merge will regenerate it cleanly from the updated proto source.

Checklist

  • go test ./pkg/detectors/rsasecurid/... passing
  • go vet / gofmt clean
  • Registered in pkg/engine/defaults

Note

Low Risk
Additive secret scanner with tests and structural guards; no changes to auth or runtime behavior beyond new findings.

Overview
Adds a new RSA SecurID detector for .sdtid XML exports: it only fires when SecurID structure markers (TKNBatch, TKNBasic, or .sdtid) are present together with a 12-digit <SN> and a <Seed> (hex or base64). Findings are emitted as a multi-part credential (serial + seed) with no verification (no public validation API).

Keywords() aligns with those structural markers so the Aho–Corasick prefilter does not skip <TKNBasic>-only blobs. Tests cover positive/negative patterns plus prefilter/keyword coverage.

The scanner is wired into default detectors and DetectorType_RSASecurID (1059) is added in proto/detector_type.proto and the generated Go maps (full make protos may still be needed for the embedded descriptor).

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

@momomuchu momomuchu requested a review from a team July 2, 2026 09:35
@momomuchu momomuchu requested review from a team as code owners July 2, 2026 09:35
@CLAassistant

CLAassistant commented Jul 2, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread proto/detector_type.proto Outdated
Comment thread pkg/detectors/rsasecurid/rsasecurid.go
@momomuchu momomuchu force-pushed the detector-rsasecurid branch from 3c57a83 to db29e15 Compare July 2, 2026 11:40

@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 db29e15. Configure here.

DetectorType_PgAnalyzeReadKey DetectorType = 1054
DetectorType_RedHatPyxis DetectorType = 1055
DetectorType_OctopusDeploy DetectorType = 1056
DetectorType_RSASecurID DetectorType = 1058

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.

Stale descriptor blob breaks String() for new enum

High Severity

The Go constant and DetectorType_name/DetectorType_value maps were manually updated for RSASecurID, but the file_detector_type_proto_rawDesc binary descriptor blob was not regenerated. The String() method uses protoimpl.X.EnumStringOf which resolves names from the descriptor, not the name map. As a result, DetectorType_RSASecurID.String() returns "1058" instead of "RSASecurID", affecting engine logging, JSON output, GitHub Actions output, and dedup hashing.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit db29e15. Configure here.

@rajpratham1 rajpratham1 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.

Good addition overall, but I think the Cursor finding is valid. contextPat recognizes both and , whereas Keywords() only returns "TKNBatch" and "sdtid". Since the Aho-Corasick prefilter gates execution of FromData, a valid token containing only may never be scanned. Could you add "TKNBasic" to Keywords() (or otherwise align the prefilter with contextPat) so all supported formats are reachable?

momomuchu and others added 2 commits July 3, 2026 19:47
…fflesecurity#4395

Detects RSA SecurID software tokens distributed as .sdtid XML files. A
token export contains a <SN> element (12-digit serial number) and a <Seed>
element (the TOTP seed, either a 128-bit hex value or an AES-encrypted seed
in base64). Possession of the seed lets an attacker generate valid one-time
passcodes, so both parts are emitted as a multi-part credential
(serial + seed).

False-positive defense: results are only emitted when an RSA SecurID
structural marker (<TKNBatch>, <TKNBasic>, or the .sdtid extension) is
present, so generic XML containing unrelated <SN>/<Seed> elements is not
reported. The serial must be exactly 12 digits and the seed at least 16
characters.

No public endpoint can validate a software token, so results are
unverified. Registers the detector in pkg/engine/defaults and adds the
RSASecurID (1057) enum to proto/detector_type.proto and the generated
detector_typepb constants/maps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… tokens are scanned — review feedback trufflesecurity#5106

contextPat matches <TKNBatch, <TKNBasic and .sdtid, but Keywords() only
advertised "TKNBatch" and "sdtid". The Aho-Corasick prefilter gates FromData
on Keywords(), so a token whose only structural marker is <TKNBasic> (no
TKNBatch/sdtid literal) was dropped before ever being scanned.

Add "TKNBasic" so every literal in contextPat has a covering keyword. Adds a
BDD given/when/then test proving a <TKNBasic>-only token is now detected
end-to-end through the real prefilter path, plus a structural test asserting
every contextPat marker has a matching keyword. Existing negative controls
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@momomuchu momomuchu force-pushed the detector-rsasecurid branch from db29e15 to 73453d4 Compare July 3, 2026 17:49
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.

Add support for RSA SecurID MFA software tokens

3 participants