Repository: projectdiscovery/nuclei

Issue:
Prevent scans from scanning dupe templates
Hi there,

When pointing scans to a custom templates folder using the -t flag, Nuclei does not remove duplicate templates. Could we include a mechanism which stops the scan from scanning the same template twice?

Thanks

Rishi

Discussion:
@mastercho: There is dupe templates in official repo too, so this will make skip lots@dogancanbakir: @rxerium,
Could you please provide an example? Are you referring to duplicating entries with the same `id`?@rxerium: Yup I am. 

Its primarily when users save their own templates to a folder and the ID is the same it scans the same template twice. @mastercho: ![b7fd0d462edee6014f67d0334611d7c7](https://github.com/projectdiscovery/nuclei/assets/10222100/975824d9-5f4e-4f46-b8b5-582af537edd1)
I thought you mean dupe like this one@rxerium: That's the same thing no? The template ID is the same@mastercho: Well before template ID was as CVE then https://github.com/projectdiscovery/nuclei-templates/issues/9065 after this issue was renamed to `wp-user-enum` but for some reason renamed templates doesnt rename in local cloned repo, instead creates new template (when updating template from nuclei run) and we end up with dupe templates with different ID's, i have reported that last year but never been looked at from PD perspective. There lots of templates like that which i point from time to time in Discord when i notice dupes.@dogancanbakir: @rxerium Deduplication occurs at the request level, regardless of template IDs. To test this, you can use two identical templates, each with different requests. Internally discussing the whether we should have deduplication at template ID level.

Solution patch:
diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go
index 0698fb96..c08f52bf 100644
--- a/cmd/nuclei/main.go
+++ b/cmd/nuclei/main.go
@@ -20,6 +20,7 @@ import (
 	_ "github.com/projectdiscovery/utils/pprof"
 	stringsutil "github.com/projectdiscovery/utils/strings"
 	"github.com/rs/xid"
+	"gopkg.in/yaml.v2"
 
 	"github.com/projectdiscovery/goflags"
 	"github.com/projectdiscovery/gologger/levels"
@@ -263,6 +264,8 @@ on extensive configurability, massive extensibility and ease of use.`)
 		flagSet.StringVarP(&options.InputFileMode, "input-mode", "im", "list", fmt.Sprintf("mode of input file (%v)", provider.SupportedInputFormats())),
 		flagSet.BoolVarP(&options.FormatUseRequiredOnly, "required-only", "ro", false, "use only required fields in input format when generating requests"),
 		flagSet.BoolVarP(&options.SkipFormatValidation, "skip-format-validation", "sfv", false, "skip format validation (like missing vars) when parsing input file"),
+		flagSet.BoolVarP(&options.VarsTextTemplating, "vars-text-templating", "vtt", false, "enable text templating for vars in input file (only for yaml input mode)"),
+		flagSet.StringSliceVarP(&options.VarsFilePaths, "var-file-paths", "vfp", nil, "list of yaml file contained vars to inject into yaml input", goflags.CommaSeparatedStringSliceOptions),
 	)
 
 	flagSet.CreateGroup("templates", "Templates",
@@ -571,6 +574,7 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
 		config.DefaultConfig.SetConfigDir(customConfigDir)
 		readFlagsConfig(flagSet)
 	}
+
 	if cfgFile != "" {
 		if !fileutil.FileExists(cfgFile) {
 			options.Logger.Fatal().Msgf("given config file '%s' does not exist", cfgFile)
@@ -579,6 +583,41 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
 		if err := flagSet.MergeConfigFile(cfgFile); err != nil {
 			options.Logger.Fatal().Msgf("Could not read config: %s\n", err)
 		}
+
+		if !options.Vars.IsEmpty() {
+			// Maybe we should add vars to the config file as well even if they are set via flags?
+			file, err := os.Open(cfgFile)
+			if err != nil {
+				gologger.Fatal().Msgf("Could not open config file: %s\n", err)
+			}
+			defer func() {
+				_ = file.Close()
+			}()
+			data := make(map[string]interface{})
+			err = yaml.NewDecoder(file).Decode(&data)
+			if err != nil {
+				gologger.Fatal().Msgf("Could not decode config file: %s\n", err)
+			}
+
+			variables := data["var"]
+			if variables != nil {
+				if varSlice, ok := variables.([]interface{}); ok {
+					for _, value := range varSlice {
+						if strVal, ok := value.(string); ok {
+							err = options.Vars.Set(strVal)
+							if err != nil {
+								gologger.Warning().Msgf("Could not set variable from config file: %s\n", err)
+							}
+						} else {
+							gologger.Warning().Msgf("Skipping non-string variable in config: %#v", value)
+						}
+					}
+				} else {
+					gologger.Warning().Msgf("No 'var' section found in config file: %s", cfgFile)
+				}
+			}
+
+		}
 	}
 	if options.NewTemplatesDirectory != "" {
 		config.DefaultConfig.SetTemplatesDir(options.NewTemplatesDirectory)
diff --git a/go.mod b/go.mod
index f8ac019f..60d4ef09 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,8 @@
 module github.com/projectdiscovery/nuclei/v3
 
-go 1.24.1
+go 1.24.2
+
+toolchain go1.24.4
 
 require (
 	github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
@@ -20,12 +22,12 @@ require (
 	github.com/olekukonko/tablewriter v1.0.8
 	github.com/pkg/errors v0.9.1
 	github.com/projectdiscovery/clistats v0.1.1
-	github.com/projectdiscovery/fastdialer v0.4.7
+	github.com/projectdiscovery/fastdialer v0.4.9
 	github.com/projectdiscovery/hmap v0.0.93
 	github.com/projectdiscovery/interactsh v1.2.4
 	github.com/projectdiscovery/rawhttp v0.1.90
-	github.com/projectdiscovery/retryabledns v1.0.106
-	github.com/projectdiscovery/retryablehttp-go v1.0.121
+	github.com/projectdiscovery/retryabledns v1.0.107
+	github.com/projectdiscovery/retryablehttp-go v1.0.123
 	github.com/projectdiscovery/yamldoc-go v1.0.6
 	github.com/remeh/sizedwaitgroup v1.0.0
 	github.com/rs/xid v1.6.0
@@ -39,22 +41,23 @@ require (
 	go.uber.org/multierr v1.11.0
 	golang.org/x/net v0.43.0
 	golang.org/x/oauth2 v0.30.0
-	golang.org/x/text v0.28.0
+	golang.org/x/text v0.29.0
 	gopkg.in/yaml.v2 v2.4.0
 )
 
 require (
-	code.gitea.io/sdk/gitea v0.21.0
+	carvel.dev/ytt v0.52.0
+	code.gitea.io/sdk/gitea v0.17.0
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1
-	github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1
+	github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0
 	github.com/DataDog/gostackparse v0.7.0
-	github.com/Masterminds/semver/v3 v3.4.0
+	github.com/Masterminds/semver/v3 v3.2.1
 	github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057
 	github.com/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697
 	github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883
 	github.com/alitto/pond v1.9.2
 	github.com/antchfx/xmlquery v1.4.4
-	github.com/antchfx/xpath v1.3.4
+	github.com/antchfx/xpath v1.3.3
 	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
 	github.com/aws/aws-sdk-go-v2 v1.36.5
 	github.com/aws/aws-sdk-go-v2/config v1.29.17
@@ -87,7 +90,7 @@ require (
 	github.com/microsoft/go-mssqldb v1.9.2
 	github.com/ory/dockertest/v3 v3.12.0
 	github.com/praetorian-inc/fingerprintx v1.1.15
-	github.com/projectdiscovery/dsl v0.5.1
+	github.com/projectdiscovery/dsl v0.6.0
 	github.com/projectdiscovery/fasttemplate v0.0.2
 	github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c
 	github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
@@ -95,22 +98,23 @@ require (
 	github.com/projectdiscovery/gologger v1.1.54
 	github.com/projectdiscovery/gostruct v0.0.2
 	github.com/projectdiscovery/gozero v0.1.0
-	github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f
+	github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a
 	github.com/projectdiscovery/mapcidr v1.1.34
 	github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
-	github.com/projectdiscovery/networkpolicy v0.1.21
+	github.com/projectdiscovery/networkpolicy v0.1.23
 	github.com/projectdiscovery/ratelimit v0.0.82
 	github.com/projectdiscovery/rdap v0.9.0
 	github.com/projectdiscovery/sarif v0.0.1
 	github.com/projectdiscovery/tlsx v1.2.1
 	github.com/projectdiscovery/uncover v1.1.0
 	github.com/projectdiscovery/useragent v0.0.101
-	github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4
-	github.com/projectdiscovery/wappalyzergo v0.2.43
+	github.com/projectdiscovery/utils v0.5.0
+	github.com/projectdiscovery/wappalyzergo v0.2.45
 	github.com/redis/go-redis/v9 v9.11.0
 	github.com/seh-msft/burpxml v1.0.1
 	github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466
-	github.com/stretchr/testify v1.11.0
+	github.com/sijms/go-ora/v2 v2.9.0
+	github.com/stretchr/testify v1.11.1
 	github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9
 	github.com/testcontainers/testcontainers-go v0.38.0
 	github.com/testcontainers/testcontainers-go/modules/mongodb v0.37.0
@@ -128,7 +132,6 @@ require (
 	dario.cat/mergo v1.0.2 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
 	git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
-	github.com/42wim/httpsig v1.2.2 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
 	github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
@@ -255,6 +258,7 @@ require (
 	github.com/jcmturner/rpc/v2 v2.0.3 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
+	github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 // indirect
 	github.com/kataras/jwt v0.1.10 // indirect
 	github.com/kevinburke/ssh_config v1.2.0 // indirect
 	github.com/klauspost/compress v1.18.0 // indirect
@@ -312,7 +316,7 @@ require (
 	github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
 	github.com/projectdiscovery/asnmap v1.1.1 // indirect
 	github.com/projectdiscovery/blackrock v0.0.1 // indirect
-	github.com/projectdiscovery/cdncheck v1.1.33 // indirect
+	github.com/projectdiscovery/cdncheck v1.1.35 // indirect
 	github.com/projectdiscovery/freeport v0.0.7 // indirect
 	github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb // indirect
 	github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 // indirect
@@ -338,7 +342,7 @@ require (
 	github.com/tklauser/numcpus v0.10.0 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/ugorji/go/codec v1.2.11 // indirect
-	github.com/ulikunitz/xz v0.5.12 // indirect
+	github.com/ulikunitz/xz v0.5.15 // indirect
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
 	github.com/xanzy/ssh-agent v0.3.3 // indirect
@@ -352,7 +356,7 @@ require (
 	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
 	github.com/ysmood/fetchup v0.2.3 // indirect
 	github.com/ysmood/got v0.40.0 // indirect
-	github.com/yuin/goldmark v1.7.11 // indirect
+	github.com/yuin/goldmark v1.7.13 // indirect
 	github.com/yuin/goldmark-emoji v1.0.5 // indirect
 	github.com/zcalusic/sysinfo v1.0.2 // indirect
 	github.com/zeebo/blake3 v0.2.3 // indirect
@@ -363,7 +367,7 @@ require (
 	go.opentelemetry.io/otel/trace v1.37.0 // indirect
 	go4.org v0.0.0-20230225012048-214862532bf5 // indirect
 	golang.org/x/arch v0.3.0 // indirect
-	golang.org/x/sync v0.16.0 // indirect
+	golang.org/x/sync v0.17.0 // indirect
 	gopkg.in/djherbis/times.v1 v1.3.0 // indirect
 	mellium.im/sasl v0.3.2 // indirect
 )
@@ -389,10 +393,10 @@ require (
 	goftp.io/server/v2 v2.0.1 // indirect
 	golang.org/x/crypto v0.41.0 // indirect
 	golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
-	golang.org/x/mod v0.26.0 // indirect
+	golang.org/x/mod v0.27.0 // indirect
 	golang.org/x/sys v0.35.0 // indirect
 	golang.org/x/time v0.11.0 // indirect
-	golang.org/x/tools v0.35.0
+	golang.org/x/tools v0.36.0
 	google.golang.org/protobuf v1.36.6 // indirect
 	gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
 	gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect
diff --git a/go.sum b/go.sum
index ae2cdea3..59725b25 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
 aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
 aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
+carvel.dev/ytt v0.52.0 h1:tkJPL8Gun5snVfypNXbmMKwnbwMyspcTi3Ypyso3nRY=
+carvel.dev/ytt v0.52.0/go.mod h1:QgmuU7E15EXW1r2wxTt7zExVz14IHwEG4WNMmaFBkJo=
 cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
@@ -270,8 +272,8 @@ cloud.google.com/go/vpcaccess v1.7.11/go.mod h1:a2cuAiSCI4TVK0Dt6/dRjf22qQvfY+po
 cloud.google.com/go/webrisk v1.9.11/go.mod h1:mK6M8KEO0ZI7VkrjCq3Tjzw4vYq+3c4DzlMUDVaiswE=
 cloud.google.com/go/websecurityscanner v1.6.11/go.mod h1:vhAZjksELSg58EZfUQ1BMExD+hxqpn0G0DuyCZQjiTg=
 cloud.google.com/go/workflows v1.12.10/go.mod h1:RcKqCiOmKs8wFUEf3EwWZPH5eHc7Oq0kamIyOUCk0IE=
-code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
-code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
+code.gitea.io/sdk/gitea v0.17.0 h1:8JPBss4+Jf7AE1YcfyiGrngTXE8dFSG3si/bypsTH34=
+code.gitea.io/sdk/gitea v0.17.0/go.mod h1:ndkDk99BnfiUCCYEUhpNzi0lpmApXlwRFqClBlOlEBg=
 dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
 dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -281,8 +283,6 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum
 git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a h1:3i+FJ7IpSZHL+VAjtpQeZCRhrpP0odl5XfoLBY4fxJ8=
 git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a/go.mod h1:C7hXLmFmPYPjIDGfQl1clsmQ5TMEQfmzWTrJk475bUs=
 git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
-github.com/42wim/httpsig v1.2.2 h1:ofAYoHUNs/MJOLqQ8hIxeyz2QxOz8qdSVvp3PX/oPgA=
-github.com/42wim/httpsig v1.2.2/go.mod h1:P/UYo7ytNBFwc+dg35IubuAUIs8zj5zzFIgUCEl55WY=
 github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
 github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
@@ -293,14 +293,14 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+
 github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
-github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo=
-github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4=
 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1 h1:Wgf5rZba3YZqeTNJPtvqZoBu1sBN/L4sry+u2U3Y75w=
 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1/go.mod h1:xxCBG/f/4Vbmh2XQJBsOmNdxWUY5j/s27jujKPbQf14=
 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI=
 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613EeLayJiRAJuKlBGy+m22qWG+WRg=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4=
 github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
 github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
@@ -310,6 +310,8 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mo
 github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4=
 github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
@@ -317,8 +319,8 @@ github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4p
 github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
-github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
-github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
+github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
+github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
 github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
 github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
@@ -391,9 +393,8 @@ github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1j
 github.com/antchfx/htmlquery v1.3.4/go.mod h1:K9os0BwIEmLAvTqaNSua8tXLWRWZpocZIH73OzWQbwM=
 github.com/antchfx/xmlquery v1.4.4 h1:mxMEkdYP3pjKSftxss4nUHfjBhnMk4imGoR96FRY2dg=
 github.com/antchfx/xmlquery v1.4.4/go.mod h1:AEPEEPYE9GnA2mj5Ur2L5Q5/2PycJ0N9Fusrx9b12fc=
+github.com/antchfx/xpath v1.3.3 h1:tmuPQa1Uye0Ym1Zn65vxPgfltWb/Lxu2jeqIGteJSRs=
 github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
-github.com/antchfx/xpath v1.3.4 h1:1ixrW1VnXd4HurCj7qnqnR0jo14g8JMe20Fshg1Vgz4=
-github.com/antchfx/xpath v1.3.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA=
 github.com/apache/thrift v0.17.0/go.mod h1:OLxhMRJxomX+1I/KUw03qoV3mMz16BwaKI+d4fPBx7Q=
@@ -849,6 +850,8 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO
 github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
 github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
 github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -952,6 +955,7 @@ github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3
 github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
 github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
 github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
 github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -1018,6 +1022,10 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/k14s/difflib v0.0.0-20201117154628-0c031775bf57 h1:CwBRArr+BWBopnUJhDjJw86rPL/jGbEjfHWKzTasSqE=
+github.com/k14s/difflib v0.0.0-20201117154628-0c031775bf57/go.mod h1:B0xN2MiNBGWOWi9CcfAo9LBI8IU4J1utlbOIJCsmKr4=
+github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 h1:4bcRTTSx+LKSxMWibIwzHnDNmaN1x52oEpvnjCy+8vk=
+github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368/go.mod h1:lKGj1op99m4GtQISxoD2t+K+WO/q2NzEPKvfXFQfbCA=
 github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ=
 github.com/kataras/jwt v0.1.10/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo=
 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
@@ -1237,14 +1245,14 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI
 github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60=
 github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
 github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
-github.com/projectdiscovery/cdncheck v1.1.33 h1:xQYq+ms0yaLaiK1BbfNc9pKsrnYVLhwRMF4yJWNfMn4=
-github.com/projectdiscovery/cdncheck v1.1.33/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U=
+github.com/projectdiscovery/cdncheck v1.1.35 h1:xyMnIWf2wzKH4Ii3lBNb73b/n9ee/baEiS3Ao23pyco=
+github.com/projectdiscovery/cdncheck v1.1.35/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U=
 github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE=
 github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
-github.com/projectdiscovery/dsl v0.5.1 h1:Nm6ToWtNKrhrF880qWykbub60Lw4m96ZkB43OGOsVLg=
-github.com/projectdiscovery/dsl v0.5.1/go.mod h1:m+tLImvmlEnFTuwb0Bm3DqCL6e7sWOunJyxFi27AduI=
-github.com/projectdiscovery/fastdialer v0.4.7 h1:fErLAppGZtZMGLLyeInMh4Kw/N0FXlTVh35v07dpS7I=
-github.com/projectdiscovery/fastdialer v0.4.7/go.mod h1:0Nm8GgU3Ds2Ac3/Fg59mVG40eMFYNA426PAcYqeNioM=
+github.com/projectdiscovery/dsl v0.6.0 h1:j4T6WKDx7uuhCSYjvEAySn86G7tTeEEsMeqjUauuqss=
+github.com/projectdiscovery/dsl v0.6.0/go.mod h1:m+tLImvmlEnFTuwb0Bm3DqCL6e7sWOunJyxFi27AduI=
+github.com/projectdiscovery/fastdialer v0.4.9 h1:/CTzoEsayQOrYJjB0CCa/0iNX7LSMeml6XmeyxX8ZVA=
+github.com/projectdiscovery/fastdialer v0.4.9/go.mod h1:/4f7ELi6M5sr5XOpt+q0OpP4sQV36f3bOG23n7GOQUw=
 github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
 github.com/projectdiscovery/fasttemplate v0.0.2/go.mod h1:XYWWVMxnItd+r0GbjA1GCsUopMw1/XusuQxdyAIHMCw=
 github.com/projectdiscovery/freeport v0.0.7 h1:Q6uXo/j8SaV/GlAHkEYQi8WQoPXyJWxyspx+aFmz9Qk=
@@ -1263,8 +1271,8 @@ github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mna
 github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs=
 github.com/projectdiscovery/hmap v0.0.93 h1:iIRdioT4byGJ4Hz5cOjo1fd3HFFi1MUFPv+EGYc1yng=
 github.com/projectdiscovery/hmap v0.0.93/go.mod h1:oKgtWo2QMD7BkW25ezYbFCqKO3IctZ2ByEaG2XWW0t0=
-github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f h1:Z73qF1ilD5RUsZP4Px4JImFkCTRlQ5K8uR2gm9eakw8=
-github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f/go.mod h1:hGAOnHyiq80ASpwbycv8Q32wsfcI8xtADEDw/mKPqTs=
+github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a h1:5NBp4BegAQuT3QSnbBKt05LH1nOyEeFAXYh1+aE3Nlo=
+github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a/go.mod h1:SQl92RiEuBnv1QQ8aQLC3b1lfgGHttoqUV0cTTvlzxQ=
 github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI=
 github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc=
 github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8=
@@ -1275,18 +1283,18 @@ github.com/projectdiscovery/mapcidr v1.1.34 h1:udr83vQ7oz3kEOwlsU6NC6o08leJzSDQt
 github.com/projectdiscovery/mapcidr v1.1.34/go.mod h1:1+1R6OkKSAKtWDXE9RvxXtXPoajXTYX0eiEdkqlhQqQ=
 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw1pfT6bg35NiN7yd1XKtJap5Nk6lMwQ0RNi8=
 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
-github.com/projectdiscovery/networkpolicy v0.1.21 h1:BOlYxPyrfqb5DneyuokZkRpeX5MCXLjCH4sI2hLudII=
-github.com/projectdiscovery/networkpolicy v0.1.21/go.mod h1:/DI9DZANBQ20x09mvcHA0J/3dCLBgCkEW5r5/L1b87U=
+github.com/projectdiscovery/networkpolicy v0.1.23 h1:+MVm9xHCfzmZG5WhUtjAGFvNiQNKOgxZDDed1QfpLXI=
+github.com/projectdiscovery/networkpolicy v0.1.23/go.mod h1:ILun9d4jgAfLOYf/NYjV+sKyW3tZTLMl+HyvaZuXZo0=
 github.com/projectdiscovery/ratelimit v0.0.82 h1:rtO5SQf5uQFu5zTahTaTcO06OxmG8EIF1qhdFPIyTak=
 github.com/projectdiscovery/ratelimit v0.0.82/go.mod h1:z076BrLkBb5yS7uhHNoCTf8X/BvFSGRxwQ8EzEL9afM=
 github.com/projectdiscovery/rawhttp v0.1.90 h1:LOSZ6PUH08tnKmWsIwvwv1Z/4zkiYKYOSZ6n+8RFKtw=
 github.com/projectdiscovery/rawhttp v0.1.90/go.mod h1:VZYAM25UI/wVB3URZ95ZaftgOnsbphxyAw/XnQRRz4Y=
 github.com/projectdiscovery/rdap v0.9.0 h1:wPhHx5pQ2QI+WGhyNb2PjhTl0NtB39Nk7YFZ9cp8ZGA=
 github.com/projectdiscovery/rdap v0.9.0/go.mod h1:zk4yrJFQ2Hy36Aqk+DvotYQxYAeALaCJ5ORySkff36Q=
-github.com/projectdiscovery/retryabledns v1.0.106 h1:repm5aGq5ge6fNJQbPNux7vyUhtUju7aIMEXZD9FX0A=
-github.com/projectdiscovery/retryabledns v1.0.106/go.mod h1:1W3ogENvt3Pb+Ju4AN0aE2lZy+D76Yzxsz51DqFCIk8=
-github.com/projectdiscovery/retryablehttp-go v1.0.121 h1:KQcMS7z5k3xnrTnD5G+HOVp1YRIbaB/iA+moc2lkR4c=
-github.com/projectdiscovery/retryablehttp-go v1.0.121/go.mod h1:15Usp6eLzNM/mI/jd+ucYRiyUuvm7vg2ymWRylG/Zss=
+github.com/projectdiscovery/retryabledns v1.0.107 h1:Rd1JK7hfL68xRg3RzXmw9Q6B6WSNv9bdPhUoGvvebyg=
+github.com/projectdiscovery/retryabledns v1.0.107/go.mod h1:XddeOhDpwS0qR8/T4GXRGgDQsLhtRHw3TRdMsgJs28o=
+github.com/projectdiscovery/retryablehttp-go v1.0.123 h1:jnbNlYJ64ScyMIiPNpyXXX7fVpOfoII20knO2xHH+4s=
+github.com/projectdiscovery/retryablehttp-go v1.0.123/go.mod h1:lv7L70Q/Lc+LARjk6ji+Ihd4Bjb9c/qmqLcdCH8Gzbo=
 github.com/projectdiscovery/sarif v0.0.1 h1:C2Tyj0SGOKbCLgHrx83vaE6YkzXEVrMXYRGLkKCr/us=
 github.com/projectdiscovery/sarif v0.0.1/go.mod h1:cEYlDu8amcPf6b9dSakcz2nNnJsoz4aR6peERwV+wuQ=
 github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
@@ -1297,10 +1305,10 @@ github.com/projectdiscovery/uncover v1.1.0 h1:UDp/qLZn78YZb6VPoOrfyP1vz+ojEx8VrT
 github.com/projectdiscovery/uncover v1.1.0/go.mod h1:2rXINmMe/lmVAt2jn9CpAOs9An57/JEeLZobY3Z9kUs=
 github.com/projectdiscovery/useragent v0.0.101 h1:8A+XOJ/nIH+WqW8ogLxJ/psemGp8ATQ2/GuKroJ/81E=
 github.com/projectdiscovery/useragent v0.0.101/go.mod h1:RGoRw1BQ/lJnhYMbMpEKjyAAgCaDCr/+GsULo5yEJ2I=
-github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4 h1:qQMEhfxDsiZ+Ay3dj93FuMAa7yt1XE2bxDpPSTEz/P0=
-github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4/go.mod h1:ipzU2PHYP71MaMn4jllPOpdYpdMkFD0jE3Tjak4b4eM=
-github.com/projectdiscovery/wappalyzergo v0.2.43 h1:gmjBJv2xHFBl48B0yFe2OL6v+mXe4KMLNdEmuMpqfhk=
-github.com/projectdiscovery/wappalyzergo v0.2.43/go.mod h1:N2ZzJYLz1FEyLO4oIL0scz8Z/r2eRRylKFrt3Zy25tc=
+github.com/projectdiscovery/utils v0.5.0 h1:DN7mg2DpyObLByuObXzAFEkdNRDoPUnqE5N2szd3b3c=
+github.com/projectdiscovery/utils v0.5.0/go.mod h1:eCAWMmyaNxyPWbiKv1oeYJLIKpxceHE2+NWx3Jodhqk=
+github.com/projectdiscovery/wappalyzergo v0.2.45 h1:tx0UuYw9GjDy/FMLsL9mr3HjPXoa3qS/lFnda/zQvf4=
+github.com/projectdiscovery/wappalyzergo v0.2.45/go.mod h1:1dHfTJRhrbbWBdKwl1p4QKpUDNnPYlHBBL7rEwCDdjM=
 github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas=
 github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -1373,6 +1381,8 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
 github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0=
 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE=
+github.com/sijms/go-ora/v2 v2.9.0 h1:+iQbUeTeCOFMb5BsOMgUhV8KWyrv9yjKpcK4x7+MFrg=
+github.com/sijms/go-ora/v2 v2.9.0/go.mod h1:QgFInVi3ZWyqAiJwzBQA+nbKYKH77tdp1PYoCqhR2dU=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -1419,8 +1429,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
 github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
-github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
 github.com/substrait-io/substrait-go v0.4.2/go.mod h1:qhpnLmrcvAnlZsUyPXZRqldiHapPTXC3t7xFgDi3aQg=
 github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
@@ -1469,8 +1479,8 @@ github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq
 github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
 github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
-github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
+github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
@@ -1535,8 +1545,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
-github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
-github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
+github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
+github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
 github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk=
 github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
 github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
@@ -1659,6 +1669,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
@@ -1750,8 +1761,8 @@ golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
-golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1901,8 +1912,8 @@ golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
-golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1919,6 +1930,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -2074,8 +2086,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
 golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
-golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
-golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2153,8 +2165,8 @@ golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58
 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
 golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
 golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
-golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
-golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go
index cfaf4e83..40fbaa48 100644
--- a/pkg/catalog/loader/loader.go
+++ b/pkg/catalog/loader/loader.go
@@ -25,6 +25,7 @@ import (
 	"github.com/projectdiscovery/nuclei/v3/pkg/workflows"
 	"github.com/projectdiscovery/retryablehttp-go"
 	"github.com/projectdiscovery/utils/errkit"
+	mapsutil "github.com/projectdiscovery/utils/maps"
 	sliceutil "github.com/projectdiscovery/utils/slice"
 	stringsutil "github.com/projectdiscovery/utils/strings"
 	syncutil "github.com/projectdiscovery/utils/sync"
@@ -315,6 +316,8 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
 	}
 	templatesCache := parserItem.Cache()
 
+	loadedTemplateIDs := mapsutil.NewSyncLockMap[string, struct{}]()
+
 	for templatePath := range validPaths {
 		template, _, _ := templatesCache.Has(templatePath)
 
@@ -339,6 +342,12 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
 		}
 
 		if template != nil {
+			if loadedTemplateIDs.Has(template.ID) {
+				store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", template.ID, templatePath)
+				continue
+			}
+
+			_ = loadedTemplateIDs.Set(template.ID, struct{}{})
 			template.Path = templatePath
 			store.templates = append(store.templates, template)
 		}
@@ -492,8 +501,16 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
 	templatePathMap := store.pathFilter.Match(includedTemplates)
 
 	loadedTemplates := sliceutil.NewSyncSlice[*templates.Template]()
+	loadedTemplateIDs := mapsutil.NewSyncLockMap[string, struct{}]()
 
 	loadTemplate := func(tmpl *templates.Template) {
+		if loadedTemplateIDs.Has(tmpl.ID) {
+			store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", tmpl.ID, tmpl.Path)
+			return
+		}
+
+		_ = loadedTemplateIDs.Set(tmpl.ID, struct{}{})
+
 		loadedTemplates.Append(tmpl)
 		// increment signed/unsigned counters
 		if tmpl.Verified {
diff --git a/pkg/input/formats/formats.go b/pkg/input/formats/formats.go
index a680888a..c7798286 100644
--- a/pkg/input/formats/formats.go
+++ b/pkg/input/formats/formats.go
@@ -28,6 +28,12 @@ type InputFormatOptions struct {
 	// RequiredOnly only uses required fields when generating requests
 	// instead of all fields
 	RequiredOnly bool
+	// VarsTextTemplating uses Variables and inject it into the input
+	// this is used for text templating of variables based on carvel ytt
+	// Only available for Yaml formats
+	VarsTextTemplating bool
+	// VarsFilePaths is the path to the file containing variables
+	VarsFilePaths []string
 }
 
 // Format is an interface implemented by all input formats
diff --git a/pkg/input/formats/yaml/multidoc.go b/pkg/input/formats/yaml/multidoc.go
index 6d75e033..a77375c7 100644
--- a/pkg/input/formats/yaml/multidoc.go
+++ b/pkg/input/formats/yaml/multidoc.go
@@ -1,8 +1,8 @@
 package yaml
 
 import (
+	"bytes"
 	"io"
-	"strings"
 
 	"github.com/pkg/errors"
 	"github.com/projectdiscovery/gologger"
@@ -46,23 +46,41 @@ func (j *YamlMultiDocFormat) SetOptions(options formats.InputFormatOptions) {
 // Parse parses the input and calls the provided callback
 // function for each RawRequest it discovers.
 func (j *YamlMultiDocFormat) Parse(input io.Reader, resultsCb formats.ParseReqRespCallback, filePath string) error {
-	decoder := YamlUtil.NewDecoder(input)
-	for {
-		var request proxifyRequest
-		err := decoder.Decode(&request)
-		if err == io.EOF {
-			break
+	finalInput := input
+
+	// Apply text templating if enabled
+	if j.opts.VarsTextTemplating {
+		data, err := io.ReadAll(input)
+		if err != nil {
+			return errors.Wrap(err, "could not read input")
 		}
+		tpl := []string{string(data)}
+		dvs := mapToKeyValueSlice(j.opts.Variables)
+		finalData, err := ytt(tpl, dvs, j.opts.VarsFilePaths)
 		if err != nil {
-			return errors.Wrap(err, "could not decode json file")
+			return errors.Wrap(err, "could not apply ytt templating")
+		}
+		finalInput = bytes.NewReader(finalData)
+	}
+
+	decoder := YamlUtil.NewDecoder(finalInput)
+	for {
+		var request proxifyRequest
+		if err := decoder.Decode(&request); err != nil {
+			if err == io.EOF {
+				break
+			}
+			return errors.Wrap(err, "could not decode yaml file")
 		}
-		if strings.TrimSpace(request.Request.Raw) == "" {
+
+		raw := request.Request.Raw
+		if raw == "" {
 			continue
 		}
 
-		rawRequest, err := types.ParseRawRequestWithURL(request.Request.Raw, request.URL)
+		rawRequest, err := types.ParseRawRequestWithURL(raw, request.URL)
 		if err != nil {
-			gologger.Warning().Msgf("multidoc-yaml: Could not parse raw request %s: %s\n", request.URL, err)
+			gologger.Warning().Msgf("multidoc-yaml: Could not parse raw request %s: %s", request.URL, err)
 			continue
 		}
 		resultsCb(rawRequest)
diff --git a/pkg/input/formats/yaml/ytt.go b/pkg/input/formats/yaml/ytt.go
new file mode 100644
index 00000000..faaf6ccd
--- /dev/null
+++ b/pkg/input/formats/yaml/ytt.go
@@ -0,0 +1,70 @@
+package yaml
+
+import (
+	"fmt"
+	"strings"
+
+	yttcmd "carvel.dev/ytt/pkg/cmd/template"
+	yttui "carvel.dev/ytt/pkg/cmd/ui"
+	yttfiles "carvel.dev/ytt/pkg/files"
+	"gopkg.in/yaml.v2"
+)
+
+func ytt(tpl, dvs []string, varFiles []string) ([]byte, error) {
+	// create and invoke ytt "template" command
+	templatingOptions := yttcmd.NewOptions()
+
+	input, err := templatesAsInput(tpl...)
+	if err != nil {
+		return nil, err
+	}
+
+	if len(varFiles) > 0 {
+		// Load vaarFiles into the templating options.
+		templatingOptions.DataValuesFlags.FromFiles = varFiles
+	}
+
+	// equivalent to `--data-value-yaml`
+	templatingOptions.DataValuesFlags.KVsFromYAML = dvs
+
+	// for in-memory use, pipe output to "/dev/null"
+	noopUI := yttui.NewCustomWriterTTY(false, noopWriter{}, noopWriter{})
+
+	// Evaluate the template given the configured data values...
+	output := templatingOptions.RunWithFiles(input, noopUI)
+	if output.Err != nil {
+		return nil, output.Err
+	}
+
+	return output.DocSet.AsBytes()
+}
+
+// templatesAsInput conveniently wraps one or more strings, each in a files.File, into a template.Input.
+func templatesAsInput(tpl ...string) (yttcmd.Input, error) {
+	var files []*yttfiles.File
+	for i, t := range tpl {
+		// to make this less brittle, you'll probably want to use well-defined names for `path`, here, for each input.
+		// this matters when you're processing errors which report based on these paths.
+		file, err := yttfiles.NewFileFromSource(yttfiles.NewBytesSource(fmt.Sprintf("tpl%d.yml", i), []byte(t)))
+		if err != nil {
+			return yttcmd.Input{}, err
+		}
+
+		files = append(files, file)
+	}
+
+	return yttcmd.Input{Files: files}, nil
+}
+
+func mapToKeyValueSlice(m map[string]interface{}) []string {
+	var result []string
+	for k, v := range m {
+		y, _ := yaml.Marshal(v)
+		result = append(result, fmt.Sprintf("%s=%s", k, strings.TrimSpace(string(y))))
+	}
+	return result
+}
+
+type noopWriter struct{}
+
+func (w noopWriter) Write(data []byte) (int, error) { return len(data), nil }
diff --git a/pkg/input/provider/interface.go b/pkg/input/provider/interface.go
index 32b923dd..9e1d09ab 100644
--- a/pkg/input/provider/interface.go
+++ b/pkg/input/provider/interface.go
@@ -116,6 +116,8 @@ func NewInputProvider(opts InputOptions) (InputProvider, error) {
 				Variables:            generators.MergeMaps(extraVars, opts.Options.Vars.AsMap()),
 				SkipFormatValidation: opts.Options.SkipFormatValidation,
 				RequiredOnly:         opts.Options.FormatUseRequiredOnly,
+				VarsTextTemplating:   opts.Options.VarsTextTemplating,
+				VarsFilePaths:        opts.Options.VarsFilePaths,
 			},
 		})
 	}
diff --git a/pkg/js/generated/go/liboracle/oracle.go b/pkg/js/generated/go/liboracle/oracle.go
index 67110b4c..d579c347 100644
--- a/pkg/js/generated/go/liboracle/oracle.go
+++ b/pkg/js/generated/go/liboracle/oracle.go
@@ -15,12 +15,12 @@ func init() {
 	module.Set(
 		gojs.Objects{
 			// Functions
-			"IsOracle": lib_oracle.IsOracle,
 
 			// Var and consts
 
 			// Objects / Classes
 			"IsOracleResponse": gojs.GetClassConstructor[lib_oracle.IsOracleResponse](&lib_oracle.IsOracleResponse{}),
+			"OracleClient":     gojs.GetClassConstructor[lib_oracle.OracleClient](&lib_oracle.OracleClient{}),
 		},
 	).Register()
 }
diff --git a/pkg/js/generated/ts/oracle.ts b/pkg/js/generated/ts/oracle.ts
index 852e919e..5701a4c5 100755
--- a/pkg/js/generated/ts/oracle.ts
+++ b/pkg/js/generated/ts/oracle.ts
@@ -1,33 +1,106 @@
 
 
 /**
- * IsOracle checks if a host is running an Oracle server
+ * IsOracleResponse is the response from the IsOracle function.
+ * this is returned by IsOracle function.
  * @example
  * ```javascript
  * const oracle = require('nuclei/oracle');
- * const isOracle = oracle.IsOracle('acme.com', 1521);
- * log(toJSON(isOracle));
+ * const client = new oracle.OracleClient();
+ * const isOracle = client.IsOracle('acme.com', 1521);
  * ```
  */
-export function IsOracle(host: string, port: number): IsOracleResponse | null {
-    return null;
+export interface IsOracleResponse {
+    IsOracle?: boolean,
+    Banner?: string,
 }
 
-
-
 /**
- * IsOracleResponse is the response from the IsOracle function.
- * this is returned by IsOracle function.
+ * Client is a client for Oracle database.
+ * Internally client uses go-ora driver.
  * @example
  * ```javascript
  * const oracle = require('nuclei/oracle');
- * const isOracle = oracle.IsOracle('acme.com', 1521);
+ * const client = new oracle.OracleClient();
  * ```
  */
-export interface IsOracleResponse {
-    
-    IsOracle?: boolean,
-    
-    Banner?: string,
+export class OracleClient {
+    // Constructor of OracleClient
+    constructor() {}
+
+    /**
+     * Connect connects to an Oracle database
+     * @example
+     * ```javascript
+     * const oracle = require('nuclei/oracle');
+     * const client = new oracle.OracleClient();
+     * client.Connect('acme.com', 1521, 'XE', 'user', 'password');
+     * ```
+     */
+    public Connect(host: string, port: number, serviceName: string, username: string, password: string): boolean | null {
+        return null;
+    }
+
+    /**
+     * ConnectWithDSN connects to an Oracle database using a DSN string
+     * @example
+     * ```javascript
+     * const oracle = require('nuclei/oracle');
+     * const client = new oracle.OracleClient();
+     * client.ConnectWithDSN('oracle://user:password@host:port/service', 'SELECT @@version');
+     * ```
+     */
+    public ConnectWithDSN(dsn: string): boolean | null {
+        return null;
+    }
+
+    /**
+     * IsOracle checks if a host is running an Oracle server
+     * @example
+     * ```javascript
+     * const oracle = require('nuclei/oracle');
+     * const isOracle = oracle.IsOracle('acme.com', 1521);
+     * ```
+     */
+    public IsOracle(host: string, port: number): IsOracleResponse | null {
+        return null;
+    }
+
+    /**
+     * ExecuteQuery connects to Oracle database using given credentials and executes a query.
+     * It returns the results of the query or an error if something goes wrong.
+     * @example
+     * ```javascript
+     * const oracle = require('nuclei/oracle');
+     * const client = new oracle.OracleClient();
+     * const result = client.ExecuteQuery('acme.com', 1521, 'username', 'password', 'XE', 'SELECT * FROM dual');
+     * log(to_json(result));
+     * ```
+     */
+    public ExecuteQuery(host: string, port: number, username: string, password: string, dbName: string, query: string): SQLResult | null {
+        return null;
+    }
+
+    /**
+     * ExecuteQueryWithDSN executes a query on an Oracle database using a DSN
+     * @example
+     * ```javascript
+     * const oracle = require('nuclei/oracle');
+     * const client = new oracle.OracleClient();
+     * const result = client.ExecuteQueryWithDSN('oracle://user:password@host:port/service', 'SELECT * FROM dual');
+     * log(to_json(result));
+     * ```
+     */
+    public ExecuteQueryWithDSN(dsn: string, query: string): SQLResult | null {
+        return null;
+    }
 }
 
+/**
+ * SQLResult Interface
+ */
+export interface SQLResult {
+    Count?: number,
+    Columns?: string[],
+    Rows?: any[],
+}
diff --git a/pkg/js/libs/oracle/oracle.go b/pkg/js/libs/oracle/oracle.go
index 9d4117d8..5a0a3ad0 100644
--- a/pkg/js/libs/oracle/oracle.go
+++ b/pkg/js/libs/oracle/oracle.go
@@ -2,6 +2,7 @@ package oracle
 
 import (
 	"context"
+	"database/sql"
 	"fmt"
 	"net"
 	"strconv"
@@ -9,7 +10,9 @@ import (
 
 	"github.com/praetorian-inc/fingerprintx/pkg/plugins"
 	"github.com/praetorian-inc/fingerprintx/pkg/plugins/services/oracledb"
+	"github.com/projectdiscovery/nuclei/v3/pkg/js/utils"
 	"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
+	goora "github.com/sijms/go-ora/v2"
 )
 
 type (
@@ -24,6 +27,16 @@ type (
 		IsOracle bool
 		Banner   string
 	}
+	// Client is a client for Oracle database.
+	// Internally client uses oracle/godror driver.
+	// @example
+	// ```javascript
+	// const oracle = require('nuclei/oracle');
+	// const client = new oracle.OracleClient();
+	// ```
+	OracleClient struct {
+		connector *goora.OracleConnector
+	}
 )
 
 // IsOracle checks if a host is running an Oracle server
@@ -33,7 +46,7 @@ type (
 // const isOracle = oracle.IsOracle('acme.com', 1521);
 // log(toJSON(isOracle));
 // ```
-func IsOracle(ctx context.Context, host string, port int) (IsOracleResponse, error) {
+func (c *OracleClient) IsOracle(ctx context.Context, host string, port int) (IsOracleResponse, error) {
 	executionId := ctx.Value("executionId").(string)
 	return memoizedisOracle(executionId, host, port)
 }
@@ -69,3 +82,129 @@ func isOracle(executionId string, host string, port int) (IsOracleResponse, erro
 	resp.IsOracle = true
 	return resp, nil
 }
+
+func (c *OracleClient) oracleDbInstance(connStr string, executionId string) (*goora.OracleConnector, error) {
+	if c.connector != nil {
+		return c.connector, nil
+	}
+
+	connector := goora.NewConnector(connStr)
+	oraConnector, ok := connector.(*goora.OracleConnector)
+	if !ok {
+		return nil, fmt.Errorf("failed to cast connector to OracleConnector")
+	}
+
+	// Create custom dialer wrapper
+	customDialer := &oracleCustomDialer{
+		executionId: executionId,
+	}
+
+	oraConnector.Dialer(customDialer)
+
+	c.connector = oraConnector
+
+	return oraConnector, nil
+}
+
+// Connect connects to an Oracle database
+// @example
+// ```javascript
+// const oracle = require('nuclei/oracle');
+// const client = new oracle.OracleClient;
+// client.Connect('acme.com', 1521, 'XE', 'user', 'password');
+// ```
+func (c *OracleClient) Connect(ctx context.Context, host string, port int, serviceName string, username string, password string) (bool, error) {
+	connStr := goora.BuildUrl(host, port, serviceName, username, password, nil)
+
+	return c.ConnectWithDSN(ctx, connStr)
+}
+
+func (c *OracleClient) ConnectWithDSN(ctx context.Context, dsn string) (bool, error) {
+	executionId := ctx.Value("executionId").(string)
+
+	connector, err := c.oracleDbInstance(dsn, executionId)
+	if err != nil {
+		return false, err
+	}
+
+	db := sql.OpenDB(connector)
+	defer func() {
+		_ = db.Close()
+	}()
+
+	db.SetMaxOpenConns(1)
+	db.SetMaxIdleConns(0)
+
+	// Test the connection
+	err = db.Ping()
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+// ExecuteQuery connects to MS SQL database using given credentials and executes a query.
+// It returns the results of the query or an error if something goes wrong.
+// @example
+// ```javascript
+// const oracle = require('nuclei/oracle');
+// const client = new oracle.OracleClient;
+// const result = client.ExecuteQuery('acme.com', 1521, 'username', 'password', 'XE', 'SELECT @@version');
+// log(to_json(result));
+// ```
+func (c *OracleClient) ExecuteQuery(ctx context.Context, host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) {
+	if host == "" || port <= 0 {
+		return nil, fmt.Errorf("invalid host or port")
+	}
+
+	isOracleResp, err := c.IsOracle(ctx, host, port)
+	if err != nil {
+		return nil, err
+	}
+	if !isOracleResp.IsOracle {
+		return nil, fmt.Errorf("not a oracle service")
+	}
+
+	connStr := goora.BuildUrl(host, port, dbName, username, password, nil)
+
+	return c.ExecuteQueryWithDSN(ctx, connStr, query)
+}
+
+// ExecuteQueryWithDSN executes a query on an Oracle database using a DSN
+// @example
+// ```javascript
+// const oracle = require('nuclei/oracle');
+// const client = new oracle.OracleClient;
+// const result = client.ExecuteQueryWithDSN('oracle://user:password@host:port/service', 'SELECT @@version');
+// log(to_json(result));
+// ```
+func (c *OracleClient) ExecuteQueryWithDSN(ctx context.Context, dsn string, query string) (*utils.SQLResult, error) {
+	executionId := ctx.Value("executionId").(string)
+
+	connector, err := c.oracleDbInstance(dsn, executionId)
+	if err != nil {
+		return nil, err
+	}
+	db := sql.OpenDB(connector)
+	defer func() {
+		_ = db.Close()
+	}()
+
+	db.SetMaxOpenConns(1)
+	db.SetMaxIdleConns(0)
+
+	rows, err := db.Query(query)
+	if err != nil {
+		return nil, err
+	}
+
+	data, err := utils.UnmarshalSQLRows(rows)
+	if err != nil {
+		if data != nil && len(data.Rows) > 0 {
+			return data, nil
+		}
+		return nil, err
+	}
+	return data, nil
+}
diff --git a/pkg/js/libs/oracle/oracledialer.go b/pkg/js/libs/oracle/oracledialer.go
new file mode 100644
index 00000000..47c62dc1
--- /dev/null
+++ b/pkg/js/libs/oracle/oracledialer.go
@@ -0,0 +1,42 @@
+package oracle
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"time"
+
+	"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
+)
+
+// oracleCustomDialer implements the dialer interface expected by go-ora
+type oracleCustomDialer struct {
+	executionId string
+}
+
+func (o *oracleCustomDialer) dialWithCtx(ctx context.Context, network, address string) (net.Conn, error) {
+	dialers := protocolstate.GetDialersWithId(o.executionId)
+	if dialers == nil {
+		return nil, fmt.Errorf("dialers not initialized for %s", o.executionId)
+	}
+	if !protocolstate.IsHostAllowed(o.executionId, address) {
+		// host is not valid according to network policy
+		return nil, protocolstate.ErrHostDenied.Msgf(address)
+	}
+	return dialers.Fastdialer.Dial(ctx, network, address)
+}
+
+func (o *oracleCustomDialer) Dial(network, address string) (net.Conn, error) {
+	return o.dialWithCtx(context.TODO(), network, address)
+}
+
+func (o *oracleCustomDialer) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
+	ctx, cancel := context.WithTimeout(context.Background(), timeout)
+	defer cancel()
+
+	return o.dialWithCtx(ctx, network, address)
+}
+
+func (o *oracleCustomDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
+	return o.dialWithCtx(ctx, network, address)
+}
diff --git a/pkg/protocols/javascript/testcases/oracle-auth-test.yaml b/pkg/protocols/javascript/testcases/oracle-auth-test.yaml
new file mode 100644
index 00000000..527bfec6
--- /dev/null
+++ b/pkg/protocols/javascript/testcases/oracle-auth-test.yaml
@@ -0,0 +1,29 @@
+id: oracle-auth-test
+
+info:
+  name: Oracle - Authentication Test
+  author: pdteam
+  severity: info
+  tags: js,oracle,network,auth
+
+javascript:
+  - pre-condition: |
+      isPortOpen(Host,Port);
+    code: |
+      let o = require('nuclei/oracle');
+      let c = o.OracleClient();
+      c.Connect(Host, Port, ServiceName, User, Pass);
+      
+    args:
+      ServiceName: "XE"
+      Host: "{{Host}}"
+      Port: "1521"
+      User: "system"
+      Pass: "{{passwords}}"
+    payloads:
+      passwords:
+        - mysecret
+    matchers:
+      - type: dsl
+        dsl:
+          - "response == true"
\ No newline at end of file
diff --git a/pkg/types/types.go b/pkg/types/types.go
index 48c186c8..26e98ba6 100644
--- a/pkg/types/types.go
+++ b/pkg/types/types.go
@@ -421,6 +421,10 @@ type Options struct {
 	FormatUseRequiredOnly bool
 	// SkipFormatValidation is used to skip format validation
 	SkipFormatValidation bool
+	// VarsTextTemplating is used to inject variables into yaml input files
+	VarsTextTemplating bool
+	// VarsFilePaths is  used to inject variables into yaml input files from a file
+	VarsFilePaths goflags.StringSlice
 	// PayloadConcurrency is the number of concurrent payloads to run per template
 	PayloadConcurrency int
 	// ProbeConcurrency is the number of concurrent http probes to run with httpx



Test patch:
diff --git a/cmd/integration-test/javascript.go b/cmd/integration-test/javascript.go
index e45f122c..61516abd 100644
--- a/cmd/integration-test/javascript.go
+++ b/cmd/integration-test/javascript.go
@@ -15,13 +15,15 @@ var jsTestcases = []TestCaseInfo{
 	{Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
 	{Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}},
 	{Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNetHttps{}},
+	{Path: "protocols/javascript/oracle-auth-test.yaml", TestCase: &javascriptOracleAuthTest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
 }
 
 var (
-	redisResource *dockertest.Resource
-	sshResource   *dockertest.Resource
-	pool          *dockertest.Pool
-	defaultRetry  = 3
+	redisResource  *dockertest.Resource
+	sshResource    *dockertest.Resource
+	oracleResource *dockertest.Resource
+	pool           *dockertest.Pool
+	defaultRetry   = 3
 )
 
 type javascriptNetHttps struct{}
@@ -98,6 +100,38 @@ func (j *javascriptSSHServerFingerprint) Execute(filePath string) error {
 	return multierr.Combine(errs...)
 }
 
+type javascriptOracleAuthTest struct{}
+
+func (j *javascriptOracleAuthTest) Execute(filePath string) error {
+	if oracleResource == nil || pool == nil {
+		// skip test as oracle is not running
+		return nil
+	}
+	tempPort := oracleResource.GetPort("1521/tcp")
+	finalURL := "localhost:" + tempPort
+	defer purge(oracleResource)
+	errs := []error{}
+	for i := 0; i < defaultRetry; i++ {
+		results := []string{}
+		var err error
+		_ = pool.Retry(func() error {
+			//let ssh server start
+			time.Sleep(3 * time.Second)
+			results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug)
+			return nil
+		})
+		if err != nil {
+			return err
+		}
+		if err := expectResultsCount(results, 1); err == nil {
+			return nil
+		} else {
+			errs = append(errs, err)
+		}
+	}
+	return multierr.Combine(errs...)
+}
+
 // purge any given resource if it is not nil
 func purge(resource *dockertest.Resource) {
 	if resource != nil && pool != nil {
@@ -163,4 +197,23 @@ func init() {
 	if err := sshResource.Expire(30); err != nil {
 		log.Printf("Could not expire resource: %s", err)
 	}
+
+	// setup a temporary oracle instance
+	oracleResource, err = pool.RunWithOptions(&dockertest.RunOptions{
+		Repository: "gvenzl/oracle-xe",
+		Tag:        "latest",
+		Env: []string{
+			"ORACLE_PASSWORD=mysecret",
+		},
+		Platform: "linux/amd64",
+	})
+	if err != nil {
+		log.Printf("Could not start Oracle resource: %s", err)
+		return
+	}
+
+	// by default expire after 30 sec
+	if err := oracleResource.Expire(30); err != nil {
+		log.Printf("Could not expire Oracle resource: %s", err)
+	}
 }
diff --git a/integration_tests/fuzz/fuzz-body.yaml b/integration_tests/fuzz/fuzz-body.yaml
new file mode 100644
index 00000000..01a3006f
--- /dev/null
+++ b/integration_tests/fuzz/fuzz-body.yaml
@@ -0,0 +1,38 @@
+id: fuzz-body
+
+info:
+  name: fuzzing error sqli payloads in http req body
+  author: pdteam
+  severity: info
+  description: |
+    This template attempts to find SQL injection vulnerabilities by fuzzing http body
+    It automatically handles and parses json,xml,multipart form and x-www-form-urlencoded data
+    and performs fuzzing on the value of every key
+
+http:
+  - pre-condition:
+      - type: dsl
+        dsl:
+          - method != "GET"
+          - method != "HEAD"
+        condition: and
+    
+    payloads:
+      injection:
+        - "'"
+        - "\""
+        - ";"
+    
+    fuzzing:
+      - part: body
+        type: postfix
+        mode: single
+        fuzz:
+          - '{{injection}}'
+  
+    stop-at-first-match: true
+    matchers:
+      - type: word
+        words:
+          - "unrecognized token:"
+          - "null"
diff --git a/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml
new file mode 100644
index 00000000..b40ece63
--- /dev/null
+++ b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml
@@ -0,0 +1,25 @@
+#@ load("@ytt:data", "data")
+#@ load("@ytt:json", "json")
+
+#@ def get_value(key, default=""):
+#@   if hasattr(data.values, key):
+#@     return str(getattr(data.values, key))
+#@   else:
+#@     return default
+#@   end
+#@ end
+
+timestamp: 2024-02-20T19:24:13+05:32
+url: https://ginandjuice.shop/users/3
+request:
+  #@yaml/text-templated-strings
+  raw: |+
+    POST /users/3 HTTP/1.1
+    Host: ginandjuice.shop
+    Authorization: Bearer (@= get_value("token", "3x4mpl3t0k3n") @)
+    Accept-Encoding: gzip
+    Content-Type: application/x-www-form-urlencoded
+    Connection: close
+    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
+
+    foo=(@= json.encode(data.values.foo) @)&bar=(@= get_value("bar") @)&debug=(@= get_value("debug", "false") @)
\ No newline at end of file
diff --git a/pkg/input/formats/testdata/ytt/ytt-profile.yaml b/pkg/input/formats/testdata/ytt/ytt-profile.yaml
new file mode 100644
index 00000000..01e794ad
--- /dev/null
+++ b/pkg/input/formats/testdata/ytt/ytt-profile.yaml
@@ -0,0 +1,11 @@
+list: pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml
+input-mode: yaml
+templates: 
+  - integration_tests/fuzz/fuzz-body.yaml
+var:
+  - debug=true
+  - bar=bar
+vars-text-templating: true
+var-file-paths:
+  - pkg/input/formats/testdata/ytt/ytt-vars.yaml
+dast: true 
\ No newline at end of file
diff --git a/pkg/input/formats/testdata/ytt/ytt-vars.yaml b/pkg/input/formats/testdata/ytt/ytt-vars.yaml
new file mode 100644
index 00000000..625ba7dd
--- /dev/null
+++ b/pkg/input/formats/testdata/ytt/ytt-vars.yaml
@@ -0,0 +1,3 @@
+token: foobar 
+foo: 
+  bar: baz
\ No newline at end of file
diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go
index efc7733e..40d078a0 100644
--- a/pkg/input/formats/yaml/multidoc_test.go
+++ b/pkg/input/formats/yaml/multidoc_test.go
@@ -2,8 +2,10 @@ package yaml
 
 import (
 	"os"
+	"strings"
 	"testing"
 
+	"github.com/projectdiscovery/nuclei/v3/pkg/input/formats"
 	"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
 	"github.com/stretchr/testify/require"
 )
@@ -33,3 +35,48 @@ func TestYamlFormatterParse(t *testing.T) {
 	require.Len(t, urls, len(expectedUrls), "invalid number of urls")
 	require.ElementsMatch(t, urls, expectedUrls, "invalid urls")
 }
+
+func TestYamlFormatterParseWithVariables(t *testing.T) {
+	format := New()
+	proxifyYttFile := "../testdata/ytt/ginandjuice.ytt.yaml"
+
+	expectedUrls := []string{
+		"https://ginandjuice.shop/users/3",
+	}
+
+	format.SetOptions(formats.InputFormatOptions{
+		VarsTextTemplating: true,
+		Variables: map[string]interface{}{
+			"foo": "catalog",
+			"bar": "product",
+		},
+	})
+	file, err := os.Open(proxifyYttFile)
+	require.Nilf(t, err, "error opening proxify ytt input file: %v", err)
+	defer func() {
+		_ = file.Close()
+	}()
+
+	var urls []string
+	err = format.Parse(file, func(request *types.RequestResponse) bool {
+		urls = append(urls, request.URL.String())
+		expectedRaw := `POST /users/3 HTTP/1.1
+Host: ginandjuice.shop
+Authorization: Bearer 3x4mpl3t0k3n
+Accept-Encoding: gzip
+Content-Type: application/x-www-form-urlencoded
+Connection: close
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
+
+foo="catalog"&bar=product&debug=false`
+		normalised := strings.ReplaceAll(request.Request.Raw, "\r\n", "\n")
+		require.Equal(t, expectedRaw, strings.TrimSuffix(normalised, "\n"), "request raw does not match expected value")
+
+		return false
+	}, proxifyYttFile)
+
+	require.Nilf(t, err, "error parsing yaml file: %v", err)
+	require.Len(t, urls, len(expectedUrls), "invalid number of urls")
+	require.ElementsMatch(t, urls, expectedUrls, "invalid urls")
+
+}