2023-04-19 21:58:48 +05:30
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
import (
|
2023-05-12 05:17:19 +05:30
|
|
|
"bytes"
|
2023-04-19 21:58:48 +05:30
|
|
|
"crypto/md5"
|
|
|
|
|
"fmt"
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
2025-05-27 17:16:26 +08:00
|
|
|
"slices"
|
2023-04-19 21:58:48 +05:30
|
|
|
"strings"
|
2025-07-09 14:47:26 -05:00
|
|
|
"sync"
|
2023-04-19 21:58:48 +05:30
|
|
|
|
|
|
|
|
"github.com/projectdiscovery/gologger"
|
2025-02-11 04:31:37 +07:00
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
|
2023-10-16 14:34:52 +05:30
|
|
|
"github.com/projectdiscovery/utils/env"
|
2025-08-20 05:28:23 +05:30
|
|
|
"github.com/projectdiscovery/utils/errkit"
|
2023-04-19 21:58:48 +05:30
|
|
|
fileutil "github.com/projectdiscovery/utils/file"
|
|
|
|
|
folderutil "github.com/projectdiscovery/utils/folder"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// DefaultConfig is the default nuclei configuration
|
|
|
|
|
// all config values and default are centralized here
|
|
|
|
|
var DefaultConfig *Config
|
|
|
|
|
|
|
|
|
|
type Config struct {
|
|
|
|
|
TemplatesDirectory string `json:"nuclei-templates-directory,omitempty"`
|
|
|
|
|
|
2023-04-19 17:42:52 -04:00
|
|
|
// customtemplates exists in templates directory with the name of custom-templates provider
|
2023-08-01 14:33:43 -04:00
|
|
|
// below custom paths are absolute paths to respective custom-templates directories
|
2023-04-19 21:58:48 +05:30
|
|
|
CustomS3TemplatesDirectory string `json:"custom-s3-templates-directory"`
|
2023-08-01 14:33:43 -04:00
|
|
|
CustomGitHubTemplatesDirectory string `json:"custom-github-templates-directory"`
|
2023-04-19 17:42:52 -04:00
|
|
|
CustomGitLabTemplatesDirectory string `json:"custom-gitlab-templates-directory"`
|
|
|
|
|
CustomAzureTemplatesDirectory string `json:"custom-azure-templates-directory"`
|
2023-04-19 21:58:48 +05:30
|
|
|
|
2023-10-17 17:44:13 +05:30
|
|
|
TemplateVersion string `json:"nuclei-templates-version,omitempty"`
|
|
|
|
|
NucleiIgnoreHash string `json:"nuclei-ignore-hash,omitempty"`
|
|
|
|
|
LogAllEvents bool `json:"-"` // when enabled logs all events (more than verbose)
|
|
|
|
|
HideTemplateSigWarning bool `json:"-"` // when enabled disables template signature warning
|
2023-04-19 21:58:48 +05:30
|
|
|
|
2023-08-01 14:33:43 -04:00
|
|
|
// LatestXXX are not meant to be used directly and is used as
|
2023-04-19 21:58:48 +05:30
|
|
|
// local cache of nuclei version check endpoint
|
|
|
|
|
// these fields are only update during nuclei version check
|
|
|
|
|
// TODO: move these fields to a separate unexported struct as they are not meant to be used directly
|
2025-07-09 14:47:26 -05:00
|
|
|
LatestNucleiVersion string `json:"nuclei-latest-version"`
|
|
|
|
|
LatestNucleiTemplatesVersion string `json:"nuclei-templates-latest-version"`
|
|
|
|
|
LatestNucleiIgnoreHash string `json:"nuclei-latest-ignore-hash,omitempty"`
|
|
|
|
|
Logger *gologger.Logger `json:"-"` // logger
|
2023-04-19 21:58:48 +05:30
|
|
|
|
|
|
|
|
// internal / unexported fields
|
2024-05-25 00:29:04 +05:30
|
|
|
disableUpdates bool `json:"-"` // disable updates both version check and template updates
|
|
|
|
|
homeDir string `json:"-"` // User Home Directory
|
|
|
|
|
configDir string `json:"-"` // Nuclei Global Config Directory
|
|
|
|
|
debugArgs []string `json:"-"` // debug args
|
2025-07-09 14:47:26 -05:00
|
|
|
|
|
|
|
|
m sync.Mutex
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
|
2023-11-11 02:12:27 +03:00
|
|
|
// IsCustomTemplate determines whether a given template is custom-built or part of the official Nuclei templates.
|
|
|
|
|
// It checks if the template's path matches any of the predefined custom template directories
|
|
|
|
|
// (such as S3, GitHub, GitLab, and Azure directories). If the template resides in any of these directories,
|
|
|
|
|
// it is considered custom. Additionally, if the template's path does not start with the main Nuclei TemplatesDirectory,
|
|
|
|
|
// it is also considered custom. This function assumes that template paths are either absolute
|
|
|
|
|
// or relative to the same base as the paths configured in DefaultConfig.
|
|
|
|
|
func (c *Config) IsCustomTemplate(templatePath string) bool {
|
|
|
|
|
customDirs := []string{
|
|
|
|
|
c.CustomS3TemplatesDirectory,
|
|
|
|
|
c.CustomGitHubTemplatesDirectory,
|
|
|
|
|
c.CustomGitLabTemplatesDirectory,
|
|
|
|
|
c.CustomAzureTemplatesDirectory,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, dir := range customDirs {
|
|
|
|
|
if strings.HasPrefix(templatePath, dir) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return !strings.HasPrefix(templatePath, c.TemplatesDirectory)
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
// WriteVersionCheckData writes version check data to config file
|
|
|
|
|
func (c *Config) WriteVersionCheckData(ignorehash, nucleiVersion, templatesVersion string) error {
|
|
|
|
|
updated := false
|
|
|
|
|
if ignorehash != "" && c.LatestNucleiIgnoreHash != ignorehash {
|
|
|
|
|
c.LatestNucleiIgnoreHash = ignorehash
|
|
|
|
|
updated = true
|
|
|
|
|
}
|
|
|
|
|
if nucleiVersion != "" && c.LatestNucleiVersion != nucleiVersion {
|
|
|
|
|
c.LatestNucleiVersion = nucleiVersion
|
|
|
|
|
updated = true
|
|
|
|
|
}
|
|
|
|
|
if templatesVersion != "" && c.LatestNucleiTemplatesVersion != templatesVersion {
|
|
|
|
|
c.LatestNucleiTemplatesVersion = templatesVersion
|
|
|
|
|
updated = true
|
|
|
|
|
}
|
|
|
|
|
// write config to disk if any of the fields are updated
|
|
|
|
|
if updated {
|
|
|
|
|
return c.WriteTemplatesConfig()
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 13:17:27 +05:30
|
|
|
// GetTemplateDir returns the nuclei templates directory absolute path
|
|
|
|
|
func (c *Config) GetTemplateDir() string {
|
|
|
|
|
val, _ := filepath.Abs(c.TemplatesDirectory)
|
|
|
|
|
return val
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
// DisableUpdateCheck disables update check and template updates
|
|
|
|
|
func (c *Config) DisableUpdateCheck() {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.m.Lock()
|
|
|
|
|
defer c.m.Unlock()
|
2023-04-19 21:58:48 +05:30
|
|
|
c.disableUpdates = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CanCheckForUpdates returns true if update check is enabled
|
|
|
|
|
func (c *Config) CanCheckForUpdates() bool {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.m.Lock()
|
|
|
|
|
defer c.m.Unlock()
|
2023-04-19 21:58:48 +05:30
|
|
|
return !c.disableUpdates
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NeedsTemplateUpdate returns true if template installation/update is required
|
|
|
|
|
func (c *Config) NeedsTemplateUpdate() bool {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.m.Lock()
|
|
|
|
|
defer c.m.Unlock()
|
2023-04-19 21:58:48 +05:30
|
|
|
return !c.disableUpdates && (c.TemplateVersion == "" || IsOutdatedVersion(c.TemplateVersion, c.LatestNucleiTemplatesVersion) || !fileutil.FolderExists(c.TemplatesDirectory))
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-01 14:33:43 -04:00
|
|
|
// NeedsIgnoreFileUpdate returns true if Ignore file hash is different (aka ignore file is outdated)
|
2023-04-19 21:58:48 +05:30
|
|
|
func (c *Config) NeedsIgnoreFileUpdate() bool {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.m.Lock()
|
|
|
|
|
defer c.m.Unlock()
|
2023-04-19 21:58:48 +05:30
|
|
|
return c.NucleiIgnoreHash == "" || c.NucleiIgnoreHash != c.LatestNucleiIgnoreHash
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UpdateNucleiIgnoreHash updates the nuclei ignore hash in config
|
|
|
|
|
func (c *Config) UpdateNucleiIgnoreHash() error {
|
|
|
|
|
// calculate hash of ignore file and update config
|
|
|
|
|
ignoreFilePath := c.GetIgnoreFilePath()
|
|
|
|
|
if fileutil.FileExists(ignoreFilePath) {
|
|
|
|
|
bin, err := os.ReadFile(ignoreFilePath)
|
|
|
|
|
if err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New("could not read nuclei ignore file"), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
c.NucleiIgnoreHash = fmt.Sprintf("%x", md5.Sum(bin))
|
|
|
|
|
// write config to disk
|
|
|
|
|
return c.WriteTemplatesConfig()
|
|
|
|
|
}
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.New("config: ignore file not found: could not update nuclei ignore hash").Build()
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetConfigDir returns the nuclei configuration directory
|
|
|
|
|
func (c *Config) GetConfigDir() string {
|
|
|
|
|
return c.configDir
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 13:17:27 +05:30
|
|
|
// GetKeysDir returns the nuclei signer keys directory
|
|
|
|
|
func (c *Config) GetKeysDir() string {
|
|
|
|
|
return filepath.Join(c.configDir, "keys")
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 17:42:52 -04:00
|
|
|
// GetAllCustomTemplateDirs returns all custom template directories
|
|
|
|
|
func (c *Config) GetAllCustomTemplateDirs() []string {
|
2023-08-01 14:33:43 -04:00
|
|
|
return []string{c.CustomS3TemplatesDirectory, c.CustomGitHubTemplatesDirectory, c.CustomGitLabTemplatesDirectory, c.CustomAzureTemplatesDirectory}
|
2023-04-19 17:42:52 -04:00
|
|
|
}
|
|
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
// GetReportingConfigFilePath returns the nuclei reporting config file path
|
|
|
|
|
func (c *Config) GetReportingConfigFilePath() string {
|
|
|
|
|
return filepath.Join(c.configDir, ReportingConfigFilename)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetIgnoreFilePath returns the nuclei ignore file path
|
|
|
|
|
func (c *Config) GetIgnoreFilePath() string {
|
|
|
|
|
return filepath.Join(c.configDir, NucleiIgnoreFileName)
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-12 05:17:19 +05:30
|
|
|
func (c *Config) GetTemplateIndexFilePath() string {
|
|
|
|
|
return filepath.Join(c.TemplatesDirectory, NucleiTemplatesIndexFileName)
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-27 21:10:33 +08:00
|
|
|
// GetChecksumFilePath returns checksum file path of nuclei templates
|
2023-04-19 21:58:48 +05:30
|
|
|
func (c *Config) GetChecksumFilePath() string {
|
|
|
|
|
return filepath.Join(c.TemplatesDirectory, NucleiTemplatesCheckSumFileName)
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-27 21:10:33 +08:00
|
|
|
// GetFlagsConfigFilePath returns the nuclei cli config file path
|
2023-04-19 21:58:48 +05:30
|
|
|
func (c *Config) GetFlagsConfigFilePath() string {
|
2023-07-17 15:23:10 -04:00
|
|
|
return filepath.Join(c.configDir, CLIConfigFileName)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetNewAdditions returns new template additions in current template release
|
|
|
|
|
// if .new-additions file is not present empty slice is returned
|
|
|
|
|
func (c *Config) GetNewAdditions() []string {
|
|
|
|
|
arr := []string{}
|
|
|
|
|
newAdditionsPath := filepath.Join(c.TemplatesDirectory, NewTemplateAdditionsFileName)
|
|
|
|
|
if !fileutil.FileExists(newAdditionsPath) {
|
|
|
|
|
return arr
|
|
|
|
|
}
|
|
|
|
|
bin, err := os.ReadFile(newAdditionsPath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return arr
|
|
|
|
|
}
|
|
|
|
|
for _, v := range strings.Fields(string(bin)) {
|
|
|
|
|
if IsTemplate(v) {
|
|
|
|
|
arr = append(arr, v)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return arr
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-13 11:55:09 +05:30
|
|
|
// GetCacheDir returns the nuclei cache directory
|
|
|
|
|
// with new version of nuclei cache directory is changed
|
|
|
|
|
// instead of saving resume files in nuclei config directory
|
|
|
|
|
// they are saved in nuclei cache directory
|
|
|
|
|
func (c *Config) GetCacheDir() string {
|
|
|
|
|
return folderutil.AppCacheDirOrDefault(".nuclei-cache", BinaryName)
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
// SetConfigDir sets the nuclei configuration directory
|
|
|
|
|
// and appropriate changes are made to the config
|
|
|
|
|
func (c *Config) SetConfigDir(dir string) {
|
|
|
|
|
c.configDir = dir
|
|
|
|
|
if err := c.createConfigDirIfNotExists(); err != nil {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.Logger.Fatal().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if folder already exists read config or create new
|
|
|
|
|
if err := c.ReadTemplatesConfig(); err != nil {
|
|
|
|
|
// create new config
|
|
|
|
|
applyDefaultConfig()
|
|
|
|
|
if err2 := c.WriteTemplatesConfig(); err2 != nil {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.Logger.Fatal().Msgf("Could not create nuclei config file at %s: %s", c.getTemplatesConfigFilePath(), err2)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// while other config files are optional, ignore file is mandatory
|
|
|
|
|
// since it is used to ignore templates with weak matchers
|
|
|
|
|
c.copyIgnoreFile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetTemplatesDir sets the new nuclei templates directory
|
|
|
|
|
func (c *Config) SetTemplatesDir(dirPath string) {
|
|
|
|
|
if dirPath != "" && !filepath.IsAbs(dirPath) {
|
|
|
|
|
cwd, _ := os.Getwd()
|
|
|
|
|
dirPath = filepath.Join(cwd, dirPath)
|
|
|
|
|
}
|
|
|
|
|
c.TemplatesDirectory = dirPath
|
|
|
|
|
// Update the custom templates directory
|
2023-08-01 14:33:43 -04:00
|
|
|
c.CustomGitHubTemplatesDirectory = filepath.Join(dirPath, CustomGitHubTemplatesDirName)
|
2023-04-19 17:42:52 -04:00
|
|
|
c.CustomS3TemplatesDirectory = filepath.Join(dirPath, CustomS3TemplatesDirName)
|
|
|
|
|
c.CustomGitLabTemplatesDirectory = filepath.Join(dirPath, CustomGitLabTemplatesDirName)
|
|
|
|
|
c.CustomAzureTemplatesDirectory = filepath.Join(dirPath, CustomAzureTemplatesDirName)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetTemplatesVersion sets the new nuclei templates version
|
|
|
|
|
func (c *Config) SetTemplatesVersion(version string) error {
|
|
|
|
|
c.TemplateVersion = version
|
|
|
|
|
// write config to disk
|
|
|
|
|
if err := c.WriteTemplatesConfig(); err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New(fmt.Sprintf("could not write nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReadTemplatesConfig reads the nuclei templates config file
|
|
|
|
|
func (c *Config) ReadTemplatesConfig() error {
|
|
|
|
|
if !fileutil.FileExists(c.getTemplatesConfigFilePath()) {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.New(fmt.Sprintf("config: nuclei config file at %s does not exist", c.getTemplatesConfigFilePath())).Build()
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
var cfg *Config
|
|
|
|
|
bin, err := os.ReadFile(c.getTemplatesConfigFilePath())
|
|
|
|
|
if err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New(fmt.Sprintf("could not read nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
if err := json.Unmarshal(bin, &cfg); err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New(fmt.Sprintf("could not unmarshal nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
// apply config
|
|
|
|
|
c.TemplatesDirectory = cfg.TemplatesDirectory
|
|
|
|
|
c.TemplateVersion = cfg.TemplateVersion
|
|
|
|
|
c.NucleiIgnoreHash = cfg.NucleiIgnoreHash
|
|
|
|
|
c.LatestNucleiIgnoreHash = cfg.LatestNucleiIgnoreHash
|
|
|
|
|
c.LatestNucleiTemplatesVersion = cfg.LatestNucleiTemplatesVersion
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WriteTemplatesConfig writes the nuclei templates config file
|
|
|
|
|
func (c *Config) WriteTemplatesConfig() error {
|
|
|
|
|
// check if config folder exists if not create one
|
|
|
|
|
if err := c.createConfigDirIfNotExists(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
bin, err := json.Marshal(c)
|
|
|
|
|
if err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New("failed to marshal nuclei config"), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
if err = os.WriteFile(c.getTemplatesConfigFilePath(), bin, 0600); err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New(fmt.Sprintf("failed to write nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-12 05:17:19 +05:30
|
|
|
// WriteTemplatesIndex writes the nuclei templates index file
|
|
|
|
|
func (c *Config) WriteTemplatesIndex(index map[string]string) error {
|
|
|
|
|
indexFile := c.GetTemplateIndexFilePath()
|
|
|
|
|
var buff bytes.Buffer
|
|
|
|
|
for k, v := range index {
|
|
|
|
|
_, _ = buff.WriteString(k + "," + v + "\n")
|
|
|
|
|
}
|
|
|
|
|
return os.WriteFile(indexFile, buff.Bytes(), 0600)
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
// getTemplatesConfigFilePath returns configDir/.templates-config.json file path
|
|
|
|
|
func (c *Config) getTemplatesConfigFilePath() string {
|
|
|
|
|
return filepath.Join(c.configDir, TemplateConfigFileName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// createConfigDirIfNotExists creates the nuclei config directory if not exists
|
|
|
|
|
func (c *Config) createConfigDirIfNotExists() error {
|
|
|
|
|
if !fileutil.FolderExists(c.configDir) {
|
|
|
|
|
if err := fileutil.CreateFolder(c.configDir); err != nil {
|
2025-08-20 05:28:23 +05:30
|
|
|
return errkit.Append(errkit.New(fmt.Sprintf("could not create nuclei config directory at %s", c.configDir)), err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// copyIgnoreFile copies the nuclei ignore file default config directory
|
|
|
|
|
// to the current config directory
|
|
|
|
|
func (c *Config) copyIgnoreFile() {
|
|
|
|
|
if err := c.createConfigDirIfNotExists(); err != nil {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.Logger.Error().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err)
|
2023-04-19 21:58:48 +05:30
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
ignoreFilePath := c.GetIgnoreFilePath()
|
|
|
|
|
if !fileutil.FileExists(ignoreFilePath) {
|
2023-10-13 11:55:09 +05:30
|
|
|
// copy ignore file from default config directory
|
|
|
|
|
if err := fileutil.CopyFile(filepath.Join(folderutil.AppConfigDirOrDefault(FallbackConfigFolderName, BinaryName), NucleiIgnoreFileName), ignoreFilePath); err != nil {
|
2025-07-09 14:47:26 -05:00
|
|
|
c.Logger.Error().Msgf("Could not copy nuclei ignore file at %s: %s", ignoreFilePath, err)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-25 00:29:04 +05:30
|
|
|
// IsDebugArgEnabled checks if debug arg is enabled
|
|
|
|
|
// this could be a feature specific to debugging like PPROF or printing stats
|
|
|
|
|
// of max host error etc
|
|
|
|
|
func (c *Config) IsDebugArgEnabled(arg string) bool {
|
2025-05-27 17:16:26 +08:00
|
|
|
return slices.Contains(c.debugArgs, arg)
|
2024-05-25 00:29:04 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parseDebugArgs from string
|
|
|
|
|
func (c *Config) parseDebugArgs(data string) {
|
|
|
|
|
// use space as seperator instead of commas
|
|
|
|
|
tmp := strings.Fields(data)
|
|
|
|
|
for _, v := range tmp {
|
|
|
|
|
key := v
|
|
|
|
|
value := ""
|
|
|
|
|
// if it is key value pair then split it
|
|
|
|
|
if strings.Contains(v, "=") {
|
|
|
|
|
parts := strings.SplitN(v, "=", 2)
|
|
|
|
|
if len(parts) != 2 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
key, value = strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
|
|
|
|
|
}
|
|
|
|
|
if value == "false" || value == "0" {
|
|
|
|
|
// if false or disabled then skip
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
switch key {
|
|
|
|
|
case DebugArgHostErrorStats:
|
|
|
|
|
c.debugArgs = append(c.debugArgs, DebugArgHostErrorStats)
|
|
|
|
|
case DebugExportURLPattern:
|
|
|
|
|
c.debugArgs = append(c.debugArgs, DebugExportURLPattern)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
func init() {
|
2023-10-13 11:55:09 +05:30
|
|
|
ConfigDir := folderutil.AppConfigDirOrDefault(FallbackConfigFolderName, BinaryName)
|
|
|
|
|
|
|
|
|
|
if cfgDir := os.Getenv(NucleiConfigDirEnv); cfgDir != "" {
|
|
|
|
|
ConfigDir = cfgDir
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create config directory if not exists
|
2023-04-19 21:58:48 +05:30
|
|
|
if !fileutil.FolderExists(ConfigDir) {
|
|
|
|
|
if err := fileutil.CreateFolder(ConfigDir); err != nil {
|
|
|
|
|
gologger.Error().Msgf("failed to create config directory at %v got: %s", ConfigDir, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DefaultConfig = &Config{
|
|
|
|
|
homeDir: folderutil.HomeDirOrDefault(""),
|
|
|
|
|
configDir: ConfigDir,
|
2025-07-09 14:47:26 -05:00
|
|
|
Logger: gologger.DefaultLogger,
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
2023-10-16 14:34:52 +05:30
|
|
|
|
|
|
|
|
// when enabled will log events in more verbosity than -v or -debug
|
|
|
|
|
// ex: N templates are excluded
|
|
|
|
|
// with this switch enabled nuclei will print details of above N templates
|
|
|
|
|
if value := env.GetEnvOrDefault("NUCLEI_LOG_ALL", false); value {
|
|
|
|
|
DefaultConfig.LogAllEvents = true
|
|
|
|
|
}
|
2023-10-17 17:44:13 +05:30
|
|
|
if value := env.GetEnvOrDefault("HIDE_TEMPLATE_SIG_WARNING", false); value {
|
|
|
|
|
DefaultConfig.HideTemplateSigWarning = true
|
|
|
|
|
}
|
2023-10-16 14:34:52 +05:30
|
|
|
|
2023-04-19 21:58:48 +05:30
|
|
|
// try to read config from file
|
|
|
|
|
if err := DefaultConfig.ReadTemplatesConfig(); err != nil {
|
|
|
|
|
gologger.Verbose().Msgf("config file not found, creating new config file at %s", DefaultConfig.getTemplatesConfigFilePath())
|
|
|
|
|
applyDefaultConfig()
|
|
|
|
|
// write config to file
|
|
|
|
|
if err := DefaultConfig.WriteTemplatesConfig(); err != nil {
|
|
|
|
|
gologger.Error().Msgf("failed to write config file at %s got: %s", DefaultConfig.getTemplatesConfigFilePath(), err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-08 17:35:55 +07:00
|
|
|
|
2023-04-19 17:42:52 -04:00
|
|
|
// Loads/updates paths of custom templates
|
|
|
|
|
// Note: custom templates paths should not be updated in config file
|
|
|
|
|
// and even if it is changed we don't follow it since it is not expected behavior
|
|
|
|
|
// If custom templates are in default locations only then they are loaded while running nuclei
|
|
|
|
|
DefaultConfig.SetTemplatesDir(DefaultConfig.TemplatesDirectory)
|
2024-05-25 00:29:04 +05:30
|
|
|
DefaultConfig.parseDebugArgs(env.GetEnvOrDefault("NUCLEI_ARGS", ""))
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add Default Config adds default when .templates-config.json file is not present
|
|
|
|
|
func applyDefaultConfig() {
|
|
|
|
|
DefaultConfig.TemplatesDirectory = filepath.Join(DefaultConfig.homeDir, NucleiTemplatesDirName)
|
2023-04-19 17:42:52 -04:00
|
|
|
// updates all necessary paths
|
|
|
|
|
DefaultConfig.SetTemplatesDir(DefaultConfig.TemplatesDirectory)
|
2023-04-19 21:58:48 +05:30
|
|
|
}
|