Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/installer/versioncheck.go
2070 views
1
package installer
2
3
import (
4
"io"
5
"net/url"
6
"os"
7
"sync"
8
9
"github.com/projectdiscovery/gologger"
10
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
11
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
12
"github.com/projectdiscovery/retryablehttp-go"
13
updateutils "github.com/projectdiscovery/utils/update"
14
)
15
16
const (
17
pdtmNucleiVersionEndpoint = "https://api.pdtm.sh/api/v1/tools/nuclei"
18
pdtmNucleiIgnoreFileEndpoint = "https://api.pdtm.sh/api/v1/tools/nuclei/ignore"
19
)
20
21
// defaultHttpClient is http client that is only meant to be used for version check
22
// if proxy env variables are set those are reflected in this client
23
var retryableHttpClient = retryablehttp.NewClient(retryablehttp.Options{HttpClient: updateutils.DefaultHttpClient, RetryMax: 2})
24
25
// PdtmAPIResponse is the response from pdtm API for nuclei endpoint
26
type PdtmAPIResponse struct {
27
IgnoreHash string `json:"ignore-hash"`
28
Tools []struct {
29
Name string `json:"name"`
30
Version string `json:"version"`
31
} `json:"tools"`
32
}
33
34
// NucleiVersionCheck checks for the latest version of nuclei and nuclei templates
35
// and returns an error if it fails to check on success it returns nil and changes are
36
// made to the default config in config.DefaultConfig
37
func NucleiVersionCheck() error {
38
return doVersionCheck(false)
39
}
40
41
// this will be updated by features of 1.21 release (which directly provides sync.Once(func()))
42
type sdkUpdateCheck struct {
43
sync.Once
44
}
45
46
var sdkUpdateCheckInstance = &sdkUpdateCheck{}
47
48
// NucleiSDKVersionCheck checks for latest version of nuclei which running in sdk mode
49
// this only happens once per process regardless of how many times this function is called
50
func NucleiSDKVersionCheck() {
51
sdkUpdateCheckInstance.Do(func() {
52
_ = doVersionCheck(true)
53
})
54
}
55
56
// getpdtmParams returns encoded query parameters sent to update check endpoint
57
func getpdtmParams(isSDK bool) string {
58
values, err := url.ParseQuery(updateutils.GetpdtmParams(config.Version))
59
if err != nil {
60
gologger.Verbose().Msgf("error parsing update check params: %v", err)
61
return updateutils.GetpdtmParams(config.Version)
62
}
63
if isSDK {
64
values.Add("sdk", "true")
65
}
66
return values.Encode()
67
}
68
69
// UpdateIgnoreFile updates default ignore file by downloading latest ignore file
70
func UpdateIgnoreFile() error {
71
resp, err := retryableHttpClient.Get(pdtmNucleiIgnoreFileEndpoint + "?" + getpdtmParams(false))
72
if err != nil {
73
return err
74
}
75
bin, err := io.ReadAll(resp.Body)
76
if err != nil {
77
return err
78
}
79
if err := os.WriteFile(config.DefaultConfig.GetIgnoreFilePath(), bin, 0644); err != nil {
80
return err
81
}
82
return config.DefaultConfig.UpdateNucleiIgnoreHash()
83
}
84
85
func doVersionCheck(isSDK bool) error {
86
// we use global retryablehttp client so its not immeditely gc'd if any references are held
87
// and according our config we have idle connections which are shown as leaked by goleak in tests
88
// i.e we close all idle connections after our use and it doesn't affect any other part of the code
89
defer retryableHttpClient.HTTPClient.CloseIdleConnections()
90
91
resp, err := retryableHttpClient.Get(pdtmNucleiVersionEndpoint + "?" + getpdtmParams(isSDK))
92
if err != nil {
93
return err
94
}
95
defer func() {
96
_ = resp.Body.Close()
97
}()
98
bin, err := io.ReadAll(resp.Body)
99
if err != nil {
100
return err
101
}
102
var pdtmResp PdtmAPIResponse
103
if err := json.Unmarshal(bin, &pdtmResp); err != nil {
104
return err
105
}
106
var nucleiversion, templateversion string
107
for _, tool := range pdtmResp.Tools {
108
switch tool.Name {
109
case "nuclei":
110
if tool.Version != "" {
111
nucleiversion = "v" + tool.Version
112
}
113
114
case "nuclei-templates":
115
if tool.Version != "" {
116
templateversion = "v" + tool.Version
117
}
118
}
119
}
120
return config.DefaultConfig.WriteVersionCheckData(pdtmResp.IgnoreHash, nucleiversion, templateversion)
121
}
122
123