github.com/projectdiscovery/nuclei/v2@v2.9.15/internal/installer/versioncheck.go (about) 1 package installer 2 3 import ( 4 "encoding/json" 5 "io" 6 "net/url" 7 "os" 8 "runtime" 9 10 "github.com/projectdiscovery/nuclei/v2/pkg/catalog/config" 11 "github.com/projectdiscovery/retryablehttp-go" 12 updateutils "github.com/projectdiscovery/utils/update" 13 ) 14 15 const ( 16 pdtmNucleiVersionEndpoint = "https://api.pdtm.sh/api/v1/tools/nuclei" 17 pdtmNucleiIgnoreFileEndpoint = "https://api.pdtm.sh/api/v1/tools/nuclei/ignore" 18 ) 19 20 // defaultHttpClient is http client that is only meant to be used for version check 21 // if proxy env variables are set those are reflected in this client 22 var retryableHttpClient = retryablehttp.NewClient(retryablehttp.Options{HttpClient: updateutils.DefaultHttpClient, RetryMax: 2}) 23 24 // PdtmAPIResponse is the response from pdtm API for nuclei endpoint 25 type PdtmAPIResponse struct { 26 IgnoreHash string `json:"ignore-hash"` 27 Tools []struct { 28 Name string `json:"name"` 29 Version string `json:"version"` 30 } `json:"tools"` 31 } 32 33 // NucleiVersionCheck checks for the latest version of nuclei and nuclei templates 34 // and returns an error if it fails to check on success it returns nil and changes are 35 // made to the default config in config.DefaultConfig 36 func NucleiVersionCheck() error { 37 resp, err := retryableHttpClient.Get(pdtmNucleiVersionEndpoint + "?" + getpdtmParams()) 38 if err != nil { 39 return err 40 } 41 defer resp.Body.Close() 42 bin, err := io.ReadAll(resp.Body) 43 if err != nil { 44 return err 45 } 46 var pdtmResp PdtmAPIResponse 47 if err := json.Unmarshal(bin, &pdtmResp); err != nil { 48 return err 49 } 50 var nucleiversion, templateversion string 51 for _, tool := range pdtmResp.Tools { 52 switch tool.Name { 53 case "nuclei": 54 if tool.Version != "" { 55 nucleiversion = "v" + tool.Version 56 } 57 58 case "nuclei-templates": 59 if tool.Version != "" { 60 templateversion = "v" + tool.Version 61 } 62 } 63 } 64 return config.DefaultConfig.WriteVersionCheckData(pdtmResp.IgnoreHash, nucleiversion, templateversion) 65 } 66 67 // getpdtmParams returns encoded query parameters sent to update check endpoint 68 func getpdtmParams() string { 69 params := &url.Values{} 70 params.Add("os", runtime.GOOS) 71 params.Add("arch", runtime.GOARCH) 72 params.Add("go_version", runtime.Version()) 73 params.Add("v", config.Version) 74 params.Add("utm_source", getUtmSource()) 75 return params.Encode() 76 } 77 78 // UpdateIgnoreFile updates default ignore file by downloading latest ignore file 79 func UpdateIgnoreFile() error { 80 resp, err := retryableHttpClient.Get(pdtmNucleiIgnoreFileEndpoint + "?" + getpdtmParams()) 81 if err != nil { 82 return err 83 } 84 bin, err := io.ReadAll(resp.Body) 85 if err != nil { 86 return err 87 } 88 if err := os.WriteFile(config.DefaultConfig.GetIgnoreFilePath(), bin, 0644); err != nil { 89 return err 90 } 91 return config.DefaultConfig.UpdateNucleiIgnoreHash() 92 }