mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-17 15:45:27 +00:00
fix: prevent unnecessary template updates (#6379)
* test(installer): adds `TestIsOutdatedVersionFix` Signed-off-by: Dwi Siswanto <git@dw1.io> * fix: prevent unnecessary template updates when version API fails. * fix `catalog/config.IsOutdatedVersion` logic for empty version strings * add GitHub API fallback when PDTM API is unavail * only show outdated msg for actual version mismatches Signed-off-by: Dwi Siswanto <git@dw1.io> --------- Signed-off-by: Dwi Siswanto <git@dw1.io>
This commit is contained in:
parent
d569cfe864
commit
70eeb6c210
@ -46,18 +46,21 @@ const (
|
||||
// if the current version is outdated
|
||||
func IsOutdatedVersion(current, latest string) bool {
|
||||
if latest == "" {
|
||||
// if pdtm api call failed it's assumed that the current version is outdated
|
||||
// and it will be confirmed while updating from GitHub
|
||||
// this fixes `version string empty` errors
|
||||
return true
|
||||
// NOTE(dwisiswant0): if PDTM API call failed or returned empty, we
|
||||
// cannot determine if templates are outdated w/o additional checks
|
||||
// return false to avoid unnecessary updates.
|
||||
return false
|
||||
}
|
||||
|
||||
current = trimDevIfExists(current)
|
||||
currentVer, _ := semver.NewVersion(current)
|
||||
newVer, _ := semver.NewVersion(latest)
|
||||
|
||||
if currentVer == nil || newVer == nil {
|
||||
// fallback to naive comparison
|
||||
return current == latest
|
||||
// fallback to naive comparison - return true only if they are different
|
||||
return current != latest
|
||||
}
|
||||
|
||||
return newVer.GreaterThan(currentVer)
|
||||
}
|
||||
|
||||
|
||||
@ -94,7 +94,24 @@ func (t *TemplateManager) UpdateIfOutdated() error {
|
||||
if !fileutil.FolderExists(config.DefaultConfig.TemplatesDirectory) {
|
||||
return t.FreshInstallIfNotExists()
|
||||
}
|
||||
if config.DefaultConfig.NeedsTemplateUpdate() {
|
||||
|
||||
needsUpdate := config.DefaultConfig.NeedsTemplateUpdate()
|
||||
|
||||
// NOTE(dwisiswant0): if PDTM API data is not available
|
||||
// (LatestNucleiTemplatesVersion is empty) but we have a current template
|
||||
// version, so we MUST verify against GitHub directly.
|
||||
if !needsUpdate && config.DefaultConfig.LatestNucleiTemplatesVersion == "" && config.DefaultConfig.TemplateVersion != "" {
|
||||
ghrd, err := updateutils.NewghReleaseDownloader(config.OfficialNucleiTemplatesRepoName)
|
||||
if err == nil {
|
||||
latestVersion := ghrd.Latest.GetTagName()
|
||||
if config.IsOutdatedVersion(config.DefaultConfig.TemplateVersion, latestVersion) {
|
||||
needsUpdate = true
|
||||
gologger.Debug().Msgf("PDTM API unavailable, verified update needed via GitHub API: %s -> %s", config.DefaultConfig.TemplateVersion, latestVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if needsUpdate {
|
||||
return t.updateTemplatesAt(config.DefaultConfig.TemplatesDirectory)
|
||||
}
|
||||
return nil
|
||||
@ -142,7 +159,14 @@ func (t *TemplateManager) updateTemplatesAt(dir string) error {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir)
|
||||
}
|
||||
|
||||
gologger.Info().Msgf("Your current nuclei-templates %s are outdated. Latest is %s\n", config.DefaultConfig.TemplateVersion, ghrd.Latest.GetTagName())
|
||||
latestVersion := ghrd.Latest.GetTagName()
|
||||
currentVersion := config.DefaultConfig.TemplateVersion
|
||||
|
||||
if config.IsOutdatedVersion(currentVersion, latestVersion) {
|
||||
gologger.Info().Msgf("Your current nuclei-templates %s are outdated. Latest is %s\n", currentVersion, latestVersion)
|
||||
} else {
|
||||
gologger.Debug().Msgf("Updating nuclei-templates from %s to %s (forced update)\n", currentVersion, latestVersion)
|
||||
}
|
||||
|
||||
// write templates to disk
|
||||
if err := t.writeTemplatesToDisk(ghrd, dir); err != nil {
|
||||
|
||||
@ -59,3 +59,42 @@ func TestTemplateInstallation(t *testing.T) {
|
||||
require.FileExists(t, config.DefaultConfig.GetIgnoreFilePath())
|
||||
t.Logf("Installed %d templates", counter)
|
||||
}
|
||||
|
||||
func TestIsOutdatedVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
current string
|
||||
latest string
|
||||
expected bool
|
||||
desc string
|
||||
}{
|
||||
// Test the empty latest version case (main bug fix)
|
||||
{"v10.2.7", "", false, "Empty latest version should not trigger update"},
|
||||
|
||||
// Test same versions
|
||||
{"v10.2.7", "v10.2.7", false, "Same versions should not trigger update"},
|
||||
|
||||
// Test outdated version
|
||||
{"v10.2.6", "v10.2.7", true, "Older version should trigger update"},
|
||||
|
||||
// Test newer current version (edge case)
|
||||
{"v10.2.8", "v10.2.7", false, "Newer current version should not trigger update"},
|
||||
|
||||
// Test dev versions
|
||||
{"v10.2.7-dev", "v10.2.7", false, "Dev version matching release should not trigger update"},
|
||||
{"v10.2.6-dev", "v10.2.7", true, "Outdated dev version should trigger update"},
|
||||
|
||||
// Test invalid semver fallback
|
||||
{"invalid-version", "v10.2.7", true, "Invalid current version should trigger update (fallback)"},
|
||||
{"v10.2.7", "invalid-version", true, "Invalid latest version should trigger update (fallback)"},
|
||||
{"same-invalid", "same-invalid", false, "Same invalid versions should not trigger update (fallback)"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
result := config.IsOutdatedVersion(tc.current, tc.latest)
|
||||
require.Equal(t, tc.expected, result,
|
||||
"IsOutdatedVersion(%q, %q) = %t, expected %t",
|
||||
tc.current, tc.latest, result, tc.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user