Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 3 additions & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,9 @@ func (r *Runner) RunEnumeration() error {
disk.PrintDeprecatedPathsMsgIfApplicable(r.options.Silent)
templates.PrintDeprecatedProtocolNameMsgIfApplicable(r.options.Silent, r.options.Verbose)

// purge global caches primarily used for loading templates
config.DefaultConfig.PurgeGlobalCache()

// add the hosts from the metadata queries of loaded templates into input provider
if r.options.Uncover && len(r.options.UncoverQuery) == 0 {
uncoverOpts := &uncoverlib.Options{
Expand Down
2 changes: 2 additions & 0 deletions lib/multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader"
"github.com/projectdiscovery/nuclei/v3/pkg/core"
"github.com/projectdiscovery/nuclei/v3/pkg/core/inputs"
Expand Down Expand Up @@ -88,6 +89,7 @@ func (e *ThreadSafeNucleiEngine) GlobalLoadAllTemplates() error {
// GlobalResultCallback sets a callback function which will be called for each result
func (e *ThreadSafeNucleiEngine) GlobalResultCallback(callback func(event *output.ResultEvent)) {
e.eng.resultCallbacks = []func(*output.ResultEvent){callback}
config.DefaultConfig.PurgeGlobalCache()
}

// ExecuteWithCallback executes templates on targets and calls callback on each result(only if results are found)
Expand Down
22 changes: 22 additions & 0 deletions pkg/catalog/config/nucleiconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ type Config struct {
LatestNucleiTemplatesVersion string `json:"nuclei-templates-latest-version"`
LatestNucleiIgnoreHash string `json:"nuclei-latest-ignore-hash,omitempty"`

// Other AppLevel/Global Settings
DisableGlobalCachePurge bool `json:"-"` // when enabled disables purging of global cache(useful for app as service)
registerdCaches []GlobalCache `json:"-"` // registered global caches

// internal / unexported fields
disableUpdates bool `json:"-"` // disable updates both version check and template updates
homeDir string `json:"-"` // User Home Directory
Expand Down Expand Up @@ -298,6 +302,24 @@ func (c *Config) WriteTemplatesIndex(index map[string]string) error {
return os.WriteFile(indexFile, buff.Bytes(), 0600)
}

// RegisterGlobalCache registers a global cache at app level
// and is available to be purged on demand
func (c *Config) RegisterGlobalCache(cache GlobalCache) {
c.registerdCaches = append(c.registerdCaches, cache)
}

// PurgeGlobalCache purges all registered global caches
func (c *Config) PurgeGlobalCache() {
if c.DisableGlobalCachePurge {
// useful for apps running nuclei as background process
// where we don't want to purge global cache
return
}
for _, cache := range c.registerdCaches {
cache.Purge()
}
}

// getTemplatesConfigFilePath returns configDir/.templates-config.json file path
func (c *Config) getTemplatesConfigFilePath() string {
return filepath.Join(c.configDir, TemplateConfigFileName)
Expand Down
7 changes: 7 additions & 0 deletions pkg/catalog/config/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ import (
stringsutil "github.com/projectdiscovery/utils/strings"
)

// GlobalCache are global cache that have global
// scope and are not purged but can be purged
// via config.DefaultConfig
type GlobalCache interface {
Purge()
}

var knownConfigFiles = []string{"cves.json", "contributors.json", "TEMPLATES-STATS.json"}

// TemplateFormat
Expand Down
1 change: 1 addition & 0 deletions pkg/parsers/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ const (

func init() {
parsedTemplatesCache = cache.New()
config.DefaultConfig.RegisterGlobalCache(parsedTemplatesCache)

stats.NewEntry(SyntaxWarningStats, "Found %d templates with syntax warning (use -validate flag for further examination)")
stats.NewEntry(SyntaxErrorStats, "Found %d templates with syntax error (use -validate flag for further examination)")
Expand Down
21 changes: 11 additions & 10 deletions pkg/templates/cache/cache.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package cache

import (
"sync"
mapsutil "github.com/projectdiscovery/utils/maps"
)

// Templates is a cache for caching and storing templates for reuse.
type Templates struct {
items *sync.Map
items *mapsutil.SyncLockMap[string, parsedTemplateErrHolder]
}

// New returns a new templates cache
func New() *Templates {
return &Templates{items: &sync.Map{}}
return &Templates{items: mapsutil.NewSyncLockMap[string, parsedTemplateErrHolder]()}
}

type parsedTemplateErrHolder struct {
Expand All @@ -22,18 +22,19 @@ type parsedTemplateErrHolder struct {
// Has returns true if the cache has a template. The template
// is returned along with any errors if found.
func (t *Templates) Has(template string) (interface{}, error) {
value, ok := t.items.Load(template)
if !ok || value == nil {
return nil, nil
}
templateError, ok := value.(parsedTemplateErrHolder)
value, ok := t.items.Get(template)
if !ok {
return nil, nil
}
return templateError.template, templateError.err
return value.template, value.err
}

// Store stores a template with data and error
func (t *Templates) Store(template string, data interface{}, err error) {
t.items.Store(template, parsedTemplateErrHolder{template: data, err: err})
_ = t.items.Set(template, parsedTemplateErrHolder{template: data, err: err})
}

// Purge the cache
func (t *Templates) Purge() {
t.items.Clear()
}
1 change: 1 addition & 0 deletions pkg/templates/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func init() {
SignatureStats[verifier.Identifier()] = &atomic.Uint64{}
}
SignatureStats[Unsigned] = &atomic.Uint64{}
config.DefaultConfig.RegisterGlobalCache(parsedTemplatesCache)
}

// Parse parses a yaml request template file
Expand Down