From 03acc788f836627f46bda2bdb7bf4e2b0ca0217f Mon Sep 17 00:00:00 2001 From: Arun Kumar Rai <98752343+rai1612@users.noreply.github.com> Date: Wed, 1 Apr 2026 11:11:21 +0530 Subject: [PATCH] todoist: replace deprecated verification endpoint (#4828) --- pkg/detectors/todoist/todoist.go | 2 +- pkg/detectors/todoist/todoist_test.go | 52 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/pkg/detectors/todoist/todoist.go b/pkg/detectors/todoist/todoist.go index 06d11228c..f1956085c 100644 --- a/pkg/detectors/todoist/todoist.go +++ b/pkg/detectors/todoist/todoist.go @@ -46,7 +46,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.todoist.com/rest/v2/projects", nil) + req, err := http.NewRequestWithContext(ctx, "GET", "https://api.todoist.com/api/v1/projects", nil) if err != nil { continue } diff --git a/pkg/detectors/todoist/todoist_test.go b/pkg/detectors/todoist/todoist_test.go index 907b32203..4e292c7ef 100644 --- a/pkg/detectors/todoist/todoist_test.go +++ b/pkg/detectors/todoist/todoist_test.go @@ -3,6 +3,9 @@ package todoist import ( "context" "fmt" + "io" + "net/http" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -11,6 +14,12 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/engine/ahocorasick" ) +type roundTripFunc func(*http.Request) (*http.Response, error) + +func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return f(req) +} + var ( validPattern = "qpgv7z8amkp4ln55znaacezm9jy35wcayy6bya2r" invalidPattern = "qpgv7z8amkp4ln55znaa?ezm9jy35wcayy6bya2r" @@ -89,3 +98,46 @@ func TestTodoist_Pattern(t *testing.T) { }) } } + +func TestTodoist_VerificationEndpoint(t *testing.T) { + d := Scanner{} + input := fmt.Sprintf("%s token = '%s'", keyword, validPattern) + + prevClient := client + t.Cleanup(func() { + client = prevClient + }) + + called := false + client = &http.Client{ + Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + called = true + if req.URL.String() != "https://api.todoist.com/api/v1/projects" { + t.Fatalf("unexpected verification URL: %s", req.URL.String()) + } + if req.Header.Get("Authorization") == "" { + t.Fatal("missing Authorization header") + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(strings.NewReader("{}")), + Header: make(http.Header), + }, nil + }), + } + + results, err := d.FromData(context.Background(), true, []byte(input)) + if err != nil { + t.Fatalf("FromData returned error: %v", err) + } + if !called { + t.Fatal("verification HTTP request was not made") + } + if len(results) != 1 { + t.Fatalf("expected 1 result, got %d", len(results)) + } + if !results[0].Verified { + t.Fatal("expected result to be verified") + } +}