Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bab758d
[INS-241] New detector (datadogapikey) for datadog apikeys
MuneebUllahKhan222 Dec 29, 2025
a942fe2
Analyzer updated to cater endpoint
MuneebUllahKhan222 Dec 30, 2025
8d6a588
Added new tests for anlyzers
MuneebUllahKhan222 Dec 30, 2025
7951443
Removed print statement
MuneebUllahKhan222 Jan 2, 2026
c6a2b6f
resolved comments and fixed integration tests.
MuneebUllahKhan222 Jan 5, 2026
3152a40
resolved comments
MuneebUllahKhan222 Jan 5, 2026
3e3a7de
changed cli prompt
MuneebUllahKhan222 Jan 5, 2026
ffb8d69
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 7, 2026
5fa6481
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 8, 2026
30bc23c
Fixed the comments and added app key validation in analyzer
MuneebUllahKhan222 Jan 9, 2026
e2bc5d8
Merge branch 'datadogapikey-detector' of https://github.com/MuneebUll…
MuneebUllahKhan222 Jan 9, 2026
829c986
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 9, 2026
20f4f19
renamed regex variable
MuneebUllahKhan222 Jan 12, 2026
491341c
Added found verified endpoint to ExtraData
MuneebUllahKhan222 Jan 12, 2026
8dd5d50
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 19, 2026
a82c86d
Clean up Analyze function by removing comments
MuneebUllahKhan222 Jan 23, 2026
b41f6a3
[INS-286] Added support to analyze just the apikey in datadog's analyzer
MuneebUllahKhan222 Jan 26, 2026
52b1a19
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 26, 2026
a475fbf
fixed linter issue
MuneebUllahKhan222 Jan 26, 2026
19fea8a
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Jan 27, 2026
320e402
fixed comment and introduced snake case to make analyzer code cosiste…
MuneebUllahKhan222 Mar 3, 2026
9b7408b
resolved bugbot comment
MuneebUllahKhan222 Mar 3, 2026
c014553
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Mar 3, 2026
72f7248
updated protos
MuneebUllahKhan222 Mar 3, 2026
ead6fe9
resolve conflicts
MuneebUllahKhan222 Mar 5, 2026
a99512f
Merge branch 'main' into datadogapikey-detector
MuneebUllahKhan222 Mar 5, 2026
4fcd972
updated protobuffs and resolved bugbot comments
MuneebUllahKhan222 Mar 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions pkg/analyzer/analyzers/datadog/datadog.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,19 @@ func (a Analyzer) Analyze(ctx context.Context, credInfo map[string]string) (*ana
// Get appKey if provided
appKey := credInfo["appKey"]

info, err := AnalyzePermissions(a.Cfg, apiKey, appKey)
// Endpoint
endpoint := credInfo["endpoint"]
Copy link

Choose a reason for hiding this comment

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

Analyzer key names mismatch with existing datadogtoken detector

High Severity

The Analyze method now reads credInfo["api_key"], credInfo["app_key"], and credInfo["endpoint"], but the existing datadogtoken detector still populates AnalysisInfo with the old key names "apiKey" and "appKey". This means when datadogtoken verification results flow into the analyzer, apiKey will resolve to an empty string, causing AnalyzePermissions to return "api key not found in credentials info" — completely breaking analysis for the existing detector.

Fix in Cursor Fix in Web

Copy link

Choose a reason for hiding this comment

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

Analyzer key name change breaks existing datadogtoken detector

High Severity

The Analyze method changed its expected credInfo key names from "apiKey"/"appKey" to "api_key"/"app_key", but the existing datadogtoken detector (not modified in this PR) likely still populates AnalysisInfo with the old key names. This would cause the analyzer to read empty strings for both keys when invoked from the datadogtoken detector, silently breaking its analysis flow and hitting the "api key not found" error for every datadogtoken result.

Additional Locations (1)

Fix in Cursor Fix in Web


info, err := AnalyzePermissions(a.Cfg, apiKey, appKey, endpoint)
if err != nil {
return nil, err
}

fmt.Printf("SecretInfo: %+v\n", info)
return secretInfoToAnalyzerResult(info), nil
}

func AnalyzeAndPrintPermissions(cfg *config.Config, apiKey string, appKey string) {
info, err := AnalyzePermissions(cfg, apiKey, appKey)
func AnalyzeAndPrintPermissions(cfg *config.Config, apiKey, appKey, endpoint string) {
info, err := AnalyzePermissions(cfg, apiKey, appKey, endpoint)
if err != nil {
// just print the error in cli and continue as a partial success
color.Red("[x] Error : %s", err.Error())
Expand All @@ -57,16 +60,23 @@ func AnalyzeAndPrintPermissions(cfg *config.Config, apiKey string, appKey string
}

// AnalyzePermissions will collect all the scopes assigned to token along with resource it can access
func AnalyzePermissions(cfg *config.Config, apiKey string, appKey string) (*SecretInfo, error) {
func AnalyzePermissions(cfg *config.Config, apiKey, appKey, endpoint string) (*SecretInfo, error) {
// create the http client
client := analyzers.NewAnalyzeClient(cfg)

var secretInfo = &SecretInfo{}

// First detect which DataDog domain works with this API key
baseURL, err := DetectDomain(client, apiKey, appKey)
if err != nil {
return nil, fmt.Errorf("[x] %v", err)
var baseURL string
var err error

// If endpoint is provided, use it directly; otherwise detect domain
if endpoint != "" {
baseURL = endpoint + "/api"
Copy link
Contributor

Choose a reason for hiding this comment

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

issue: Let's use url.JoinPath here instead (I can't remember if I've given you my spiel about manipulating URLs as strings, but tl;dr: it's risky). There's a few places in this PR where we should change this; I won't note them though.

} else {
baseURL, err = DetectDomain(client, apiKey, appKey)
if err != nil {
return nil, fmt.Errorf("[x] %v", err)
}
}

// capture user information in secretInfo
Expand Down Expand Up @@ -114,7 +124,10 @@ func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
}

permissionBindings := secretInfoPermissionsToAnalyzerPermission(info.Permissions)
result.Bindings = analyzers.BindAllPermissions(*userResource, *permissionBindings...)

if userResource != nil && len(*permissionBindings) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: I might unify these under an if len(*permissionBindings) > 0 block; it makes it more clear that condition is required to set bindings here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

userResource != nil check is important because we deference the pointer and derefrencing a nil pointer will lead a panic

result.Bindings = analyzers.BindAllPermissions(*userResource, *permissionBindings...)
}

// Extract information from resources to create bindings
for _, resource := range info.Resources {
Expand Down
34 changes: 28 additions & 6 deletions pkg/analyzer/analyzers/datadog/datadog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ func TestAnalyzer_Analyze(t *testing.T) {
}

tests := []struct {
name string
apiKey string
appKey string
want []byte // JSON string
wantErr bool
name string
apiKey string
appKey string
endpoint string
want []byte // JSON string
wantErr bool
}{
{
name: "valid datadog credentials",
Expand All @@ -51,6 +52,27 @@ func TestAnalyzer_Analyze(t *testing.T) {
want: expectedOutput,
wantErr: false,
},
{
name: "valid datadog credentials with endpoint",
apiKey: apiKey,
appKey: appKey,
endpoint: "https://api.us5.datadoghq.com",
want: expectedOutput,
wantErr: false,
},
{
name: "valid datadog credentials with invalid endpoint",
apiKey: apiKey,
appKey: appKey,
endpoint: "https://api.eu.datadoghq.com",
want: []byte(fmt.Sprintf(`{
"AnalyzerType": %s,
"Bindings": [],
"UnboundedResources": null,
"Metadata": {}
}`, analyzers.AnalyzerTypeDatadog)),
wantErr: true,
},
{
name: "invalid credentials",
apiKey: "invalid_api_key",
Expand All @@ -63,7 +85,7 @@ func TestAnalyzer_Analyze(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := Analyzer{Cfg: &config.Config{}}
got, err := a.Analyze(ctx, map[string]string{"apiKey": tt.apiKey, "appKey": tt.appKey})
got, err := a.Analyze(ctx, map[string]string{"apiKey": tt.apiKey, "appKey": tt.appKey, "endpoint": tt.endpoint})

if (err != nil) != tt.wantErr {
t.Errorf("Analyzer.Analyze() error = %v, wantErr %v", err, tt.wantErr)
Expand Down
Loading
Loading