Skip to content

feat!(detector): timeout can be set, default is no timeout #2185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions config/vulnDictConf.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ type VulnDict struct {
SQLite3Path string

DebugSQL bool

// Timeout for entire request (type: http only)
TimeoutSec uint

// Timeout for each request (type: http only)
TimeoutSecPerRequest uint
}

// GetType returns type
Expand Down
14 changes: 10 additions & 4 deletions detector/cti.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ func getCTIsViaHTTP(cveIDs []string, urlPrefix string) (responses []ctiResponse,
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.Cti.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.Cti.TimeoutSec) * time.Second)
}
var errs []error
for i := 0; i < nReq; i++ {
select {
Expand Down Expand Up @@ -174,8 +177,11 @@ func httpGetCTI(url string, req ctiRequest, resChan chan<- ctiResponse, errChan
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.Cti.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Cti.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
Expand All @@ -186,7 +192,7 @@ func httpGetCTI(url string, req ctiRequest, resChan chan<- ctiResponse, errChan
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
if err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify); err != nil {
errChan <- xerrors.Errorf("HTTP Error %w", err)
Expand Down
20 changes: 15 additions & 5 deletions detector/cve_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ func (client goCveDictClient) fetchCveDetails(cveIDs []string) (cveDetails []cve
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.CveDict.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.CveDict.TimeoutSec) * time.Second)
}
var errs []error
for range cveIDs {
select {
Expand Down Expand Up @@ -113,15 +116,19 @@ func httpGet(key, url string, resChan chan<- response, errChan chan<- error) {
var errs []error
var resp *http.Response
f := func() (err error) {
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.CveDict.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.CveDict.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return xerrors.Errorf("HTTP GET Error, url: %s, resp: %v, err: %+v",
url, resp, errs)
}
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
Expand Down Expand Up @@ -177,7 +184,10 @@ func httpPost(url string, query map[string]string) ([]cvemodels.CveDetail, error
var errs []error
var resp *http.Response
f := func() (err error) {
req := gorequest.New().Timeout(10 * time.Second).Post(url)
req := gorequest.New().Post(url)
if config.Conf.CveDict.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.CveDict.TimeoutSecPerRequest) * time.Second)
}
for key := range query {
req = req.Send(fmt.Sprintf("%s=%s", key, query[key])).Type("json")
}
Expand All @@ -188,7 +198,7 @@ func httpPost(url string, query map[string]string) ([]cvemodels.CveDetail, error
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP POST. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP POST. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
Expand Down
14 changes: 10 additions & 4 deletions detector/exploitdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ func getExploitsViaHTTP(cveIDs []string, urlPrefix string) (
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.Exploit.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.Exploit.TimeoutSec) * time.Second)
}
var errs []error
for i := 0; i < nReq; i++ {
select {
Expand Down Expand Up @@ -209,8 +212,11 @@ func httpGetExploit(url string, req exploitRequest, resChan chan<- exploitRespon
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.Exploit.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Exploit.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
Expand All @@ -221,7 +227,7 @@ func httpGetExploit(url string, req exploitRequest, resChan chan<- exploitRespon
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
Expand Down
14 changes: 10 additions & 4 deletions detector/kevuln.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,10 @@ func getKEVulnsViaHTTP(cveIDs []string, urlPrefix string) (
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.KEVuln.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.KEVuln.TimeoutSec) * time.Second)
}
var errs []error
for i := 0; i < nReq; i++ {
select {
Expand Down Expand Up @@ -304,8 +307,11 @@ func httpGetKEVuln(url string, req kevulnRequest, resChan chan<- kevulnResponse,
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.KEVuln.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.KEVuln.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
Expand All @@ -316,7 +322,7 @@ func httpGetKEVuln(url string, req kevulnRequest, resChan chan<- kevulnResponse,
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
Expand Down
14 changes: 10 additions & 4 deletions detector/msf.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ func getMetasploitsViaHTTP(cveIDs []string, urlPrefix string) (
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.Metasploit.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.Metasploit.TimeoutSec) * time.Second)
}
var errs []error
for i := 0; i < nReq; i++ {
select {
Expand Down Expand Up @@ -175,8 +178,11 @@ func httpGetMetasploit(url string, req metasploitRequest, resChan chan<- metaspl
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.Metasploit.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Metasploit.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
Expand All @@ -187,7 +193,7 @@ func httpGetMetasploit(url string, req metasploitRequest, resChan chan<- metaspl
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
Expand Down
25 changes: 19 additions & 6 deletions gost/microsoft.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/parnurzeal/gorequest"
"golang.org/x/xerrors"

"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
Expand Down Expand Up @@ -47,14 +48,18 @@ func (ms Microsoft) DetectCVEs(r *models.ScanResult, _ bool) (nCVEs int, err err
var errs []error
var resp *http.Response
f := func() error {
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Post(u).SendStruct(content).Type("json").EndBytes()
req := gorequest.New().Post(u).SendStruct(content).Type("json")
if config.Conf.Gost.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Gost.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.EndBytes()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return xerrors.Errorf("HTTP POST error. url: %s, resp: %v, err: %+v", u, resp, errs)
}
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP POST. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP POST. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
if err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify); err != nil {
return 0, xerrors.Errorf("HTTP Error: %w", err)
Expand Down Expand Up @@ -88,14 +93,18 @@ func (ms Microsoft) DetectCVEs(r *models.ScanResult, _ bool) (nCVEs int, err err
var errs []error
var resp *http.Response
f := func() error {
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Post(u).SendStruct(content).Type("json").EndBytes()
req := gorequest.New().Post(u).SendStruct(content).Type("json")
if config.Conf.Gost.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Gost.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.EndBytes()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return xerrors.Errorf("HTTP POST error. url: %s, resp: %v, err: %+v", u, resp, errs)
}
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP POST. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP POST. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
if err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify); err != nil {
return 0, xerrors.Errorf("HTTP Error: %w", err)
Expand Down Expand Up @@ -151,14 +160,18 @@ func (ms Microsoft) DetectCVEs(r *models.ScanResult, _ bool) (nCVEs int, err err
var errs []error
var resp *http.Response
f := func() error {
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Post(u).SendStruct(content).Type("json").EndBytes()
req := gorequest.New().Post(u).SendStruct(content).Type("json")
if config.Conf.Gost.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Gost.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.EndBytes()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return xerrors.Errorf("HTTP POST error. url: %s, resp: %v, err: %+v", u, resp, errs)
}
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP POST. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP POST. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
if err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify); err != nil {
return 0, xerrors.Errorf("HTTP Error: %w", err)
Expand Down
24 changes: 17 additions & 7 deletions gost/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/parnurzeal/gorequest"
"golang.org/x/xerrors"

"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
Expand Down Expand Up @@ -59,7 +60,10 @@ func getCvesViaHTTP(cveIDs []string, urlPrefix string) (
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.Gost.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.Gost.TimeoutSec) * time.Second)
}
var errs []error
for i := 0; i < nReq; i++ {
select {
Expand All @@ -68,11 +72,11 @@ func getCvesViaHTTP(cveIDs []string, urlPrefix string) (
case err := <-errChan:
errs = append(errs, err)
case <-timeout:
return nil, xerrors.New("Timeout Fetching OVAL")
return nil, xerrors.New("Timeout Fetching Gost")
}
}
if len(errs) != 0 {
return nil, xerrors.Errorf("Failed to fetch OVAL. err: %w", errs)
return nil, xerrors.Errorf("Failed to fetch Gost. err: %w", errs)
}
return
}
Expand Down Expand Up @@ -124,7 +128,10 @@ func getCvesWithFixStateViaHTTP(r *models.ScanResult, urlPrefix, fixState string
}
}

timeout := time.After(2 * 60 * time.Second)
var timeout <-chan time.Time
if config.Conf.Gost.TimeoutSec > 0 {
timeout = time.After(time.Duration(config.Conf.Gost.TimeoutSec) * time.Second)
}
var errs []error
for i := 0; i < nReq; i++ {
select {
Expand All @@ -148,8 +155,11 @@ func httpGet(url string, req request, resChan chan<- response, errChan chan<- er
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.Gost.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.Gost.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs = req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
Expand All @@ -160,7 +170,7 @@ func httpGet(url string, req request, resChan chan<- response, errChan chan<- er
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %f seconds. err: %+v", t.Seconds(), err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
Expand Down
13 changes: 11 additions & 2 deletions oval/oval.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ func (b Base) CheckIfOvalFetched(osFamily, release string) (bool, error) {
if err != nil {
return false, xerrors.Errorf("Failed to join URLPath. err: %w", err)
}
resp, body, errs := gorequest.New().Timeout(10 * time.Second).Get(url).End()

req := gorequest.New().Get(url)
if config.Conf.OvalDict.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.OvalDict.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs := req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return false, xerrors.Errorf("HTTP GET error, url: %s, resp: %v, err: %+v", url, resp, errs)
}
Expand Down Expand Up @@ -143,7 +148,11 @@ func (b Base) CheckIfOvalFresh(osFamily, release string) (ok bool, err error) {
if err != nil {
return false, xerrors.Errorf("Failed to join URLPath. err: %w", err)
}
resp, body, errs := gorequest.New().Timeout(10 * time.Second).Get(url).End()
req := gorequest.New().Get(url)
if config.Conf.OvalDict.TimeoutSecPerRequest > 0 {
req = req.Timeout(time.Duration(config.Conf.OvalDict.TimeoutSecPerRequest) * time.Second)
}
resp, body, errs := req.End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return false, xerrors.Errorf("HTTP GET error, url: %s, resp: %v, err: %+v", url, resp, errs)
}
Expand Down
Loading
Loading