From eb33321102e2d3886f3a77d752b2fd89f761b72d Mon Sep 17 00:00:00 2001 From: vmfunc Date: Tue, 9 Jun 2026 13:56:01 -0700 Subject: [PATCH] fix(js): give supabase requests a real timeout doSupabaseRequest and the signup call used a bare http.Client{} with no timeout, so a slow supabase project could hang the whole js scan. thread the scan's --timeout down through ScanSupabase into every supabase request. --- internal/scan/js/scan.go | 2 +- internal/scan/js/supabase.go | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/scan/js/scan.go b/internal/scan/js/scan.go index 4abcd5f..3e4ae11 100644 --- a/internal/scan/js/scan.go +++ b/internal/scan/js/scan.go @@ -135,7 +135,7 @@ func JavascriptScan(url string, timeout time.Duration, threads int, logdir strin content := string(bodyBytes) charmlog.Debugf("Running supabase scanner on %s", script) - scriptSupabaseResults, err := ScanSupabase(content, script) + scriptSupabaseResults, err := ScanSupabase(content, script, timeout) if err != nil { charmlog.Errorf("Error while scanning supabase: %s", err) diff --git a/internal/scan/js/supabase.go b/internal/scan/js/supabase.go index 8f9c209..be853d1 100644 --- a/internal/scan/js/supabase.go +++ b/internal/scan/js/supabase.go @@ -70,8 +70,8 @@ type supabaseOpenAPIResponse struct { } // getSupabaseArrayResponse fetches a Supabase endpoint that returns an array. -func getSupabaseArrayResponse(projectId, path, apikey string, auth *string) (*supabaseArrayResponse, error) { - body, resp, err := doSupabaseRequest(projectId, path, apikey, auth) //nolint:bodyclose // closed in doSupabaseRequest +func getSupabaseArrayResponse(projectId, path, apikey string, auth *string, timeout time.Duration) (*supabaseArrayResponse, error) { + body, resp, err := doSupabaseRequest(projectId, path, apikey, auth, timeout) //nolint:bodyclose // closed in doSupabaseRequest if err != nil { return nil, err } @@ -95,8 +95,8 @@ func getSupabaseArrayResponse(projectId, path, apikey string, auth *string) (*su } // getSupabaseOpenAPI fetches the OpenAPI spec from Supabase. -func getSupabaseOpenAPI(projectId, apikey string, auth *string) (*supabaseOpenAPIResponse, error) { - body, _, err := doSupabaseRequest(projectId, "/rest/v1/", apikey, auth) //nolint:bodyclose // closed in doSupabaseRequest +func getSupabaseOpenAPI(projectId, apikey string, auth *string, timeout time.Duration) (*supabaseOpenAPIResponse, error) { + body, _, err := doSupabaseRequest(projectId, "/rest/v1/", apikey, auth, timeout) //nolint:bodyclose // closed in doSupabaseRequest if err != nil { return nil, err } @@ -109,8 +109,8 @@ func getSupabaseOpenAPI(projectId, apikey string, auth *string) (*supabaseOpenAP } // doSupabaseRequest performs a GET request to the Supabase API. -func doSupabaseRequest(projectId, path, apikey string, auth *string) ([]byte, *http.Response, error) { - client := http.Client{} +func doSupabaseRequest(projectId, path, apikey string, auth *string, timeout time.Duration) ([]byte, *http.Response, error) { + client := http.Client{Timeout: timeout} req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "https://"+projectId+".supabase.co"+path, http.NoBody) if err != nil { @@ -142,7 +142,7 @@ func doSupabaseRequest(projectId, path, apikey string, auth *string) ([]byte, *h return body, resp, nil } -func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error) { +func ScanSupabase(jsContent string, jsUrl string, timeout time.Duration) ([]supabaseScanResult, error) { supabaselog := log.NewWithOptions(os.Stderr, log.Options{ Prefix: "JavaScript > Supabase", }).With("url", jsUrl) @@ -182,7 +182,7 @@ func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error) } supabaselog.Infof("Found valid supabase project %s with role %s", *supabaseJwt.ProjectId, *supabaseJwt.Role) - client := http.Client{} + client := http.Client{Timeout: timeout} req, err := http.NewRequestWithContext(context.TODO(), http.MethodPost, "https://"+*supabaseJwt.ProjectId+".supabase.co/auth/v1/signup", bytes.NewBufferString(`{"email":"automated`+strconv.Itoa(int(time.Now().Unix()))+`@sif.sh","password":"automatedacct"}`)) if err != nil { @@ -219,7 +219,7 @@ func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error) var collections = []supabaseCollection{} - openAPI, err := getSupabaseOpenAPI(*supabaseJwt.ProjectId, jwt, &auth) + openAPI, err := getSupabaseOpenAPI(*supabaseJwt.ProjectId, jwt, &auth, timeout) if err != nil { return nil, err } @@ -238,7 +238,7 @@ func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error) continue } - sampleResp, err := getSupabaseArrayResponse(*supabaseJwt.ProjectId, "/rest/v1"+path, jwt, &auth) + sampleResp, err := getSupabaseArrayResponse(*supabaseJwt.ProjectId, "/rest/v1"+path, jwt, &auth, timeout) if err != nil { continue }