Repository: projectdiscovery/nuclei

Issue:
Follow-up: Text/template syntax for Jira custom fields (PR #6464)
This issue tracks follow-up work for PR #6464 which adds text/template syntax engine to Jira custom fields.

**PR Details:**
- URL: https://github.com/projectdiscovery/nuclei/pull/6464
- Author: Ice3man543
- Requested by: @Mzack9999

**Changes introduced:**
- Added TemplateContext struct to hold event-derived data
- Implemented template evaluation for Jira custom fields with text/template syntax
- Added backward compatibility for legacy  syntax
- Enhanced custom field value evaluation with template support

**Potential follow-up items:**
- Documentation updates for the new templating syntax
- Additional test coverage for edge cases
- User guide examples for complex template usage

This issue was created as requested in the PR review process.

Discussion:

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..6d0541da 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
@@ -146,6 +149,7 @@ require (
 	github.com/alecthomas/kingpin/v2 v2.4.0 // indirect
 	github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
 	github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
+	github.com/alexsnet/go-vnc v0.1.0 // indirect
 	github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect
 	github.com/andybalholm/cascadia v1.3.3 // indirect
 	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect
@@ -255,6 +259,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 +317,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 +343,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 +357,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 +368,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 +394,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..8c73280a 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=
@@ -376,6 +378,8 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu
 github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
 github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
 github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
+github.com/alexsnet/go-vnc v0.1.0 h1:vBCwPNy79WEL8V/Z5A0ngEFCvTWBAjmS048lkR2rdmY=
+github.com/alexsnet/go-vnc v0.1.0/go.mod h1:bbRsg41Sh3zvrnWsw+REKJVGZd8Of2+S0V1G0ZaBhlU=
 github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs=
 github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI=
 github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
@@ -391,9 +395,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 +852,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 +957,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 +1024,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 +1247,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 +1273,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 +1285,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 +1307,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 +1383,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 +1431,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 +1481,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 +1547,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 +1671,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 +1763,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 +1914,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 +1932,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 +2088,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 +2167,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/go/libvnc/vnc.go b/pkg/js/generated/go/libvnc/vnc.go
index 625f3776..fa060ec1 100644
--- a/pkg/js/generated/go/libvnc/vnc.go
+++ b/pkg/js/generated/go/libvnc/vnc.go
@@ -21,6 +21,7 @@ func init() {
 
 			// Objects / Classes
 			"IsVNCResponse": gojs.GetClassConstructor[lib_vnc.IsVNCResponse](&lib_vnc.IsVNCResponse{}),
+			"VNCClient":     gojs.GetClassConstructor[lib_vnc.VNCClient](&lib_vnc.VNCClient{}),
 		},
 	).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/generated/ts/vnc.ts b/pkg/js/generated/ts/vnc.ts
index 870151e2..f74edb89 100755
--- a/pkg/js/generated/ts/vnc.ts
+++ b/pkg/js/generated/ts/vnc.ts
@@ -33,3 +33,34 @@ export interface IsVNCResponse {
     Banner?: string,
 }
 
+/**
+ * VNCClient is a client for VNC servers.
+ * @example
+ * ```javascript
+ * const vnc = require('nuclei/vnc');
+ * const client = new vnc.VNCClient();
+ * ```
+ */
+export class VNCClient {
+    
+
+    // Constructor of VNCClient
+    constructor() {}
+    
+    /**
+    * Connect connects to VNC server using given password.
+    * If connection and authentication is successful, it returns true.
+    * If connection or authentication is unsuccessful, it returns false and error.
+    * The connection is closed after the function returns.
+    * @example
+    * ```javascript
+    * const vnc = require('nuclei/vnc');
+    * const client = new vnc.VNCClient();
+    * const connected = client.Connect('acme.com', 5900, 'password');
+    * ```
+    */
+    public Connect(host: string, port: number, password: string): boolean | null {
+        return null;
+    }
+}
+
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/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go
index bd28ad69..63c3e6a3 100644
--- a/pkg/js/libs/vnc/vnc.go
+++ b/pkg/js/libs/vnc/vnc.go
@@ -7,9 +7,11 @@ import (
 	"strconv"
 	"time"
 
+	vnclib "github.com/alexsnet/go-vnc"
 	"github.com/praetorian-inc/fingerprintx/pkg/plugins"
-	"github.com/praetorian-inc/fingerprintx/pkg/plugins/services/vnc"
+	vncplugin "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/vnc"
 	"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
+	stringsutil "github.com/projectdiscovery/utils/strings"
 )
 
 type (
@@ -24,8 +26,89 @@ type (
 		IsVNC  bool
 		Banner string
 	}
+
+	// VNCClient is a client for VNC servers.
+	// @example
+	// ```javascript
+	// const vnc = require('nuclei/vnc');
+	// const client = new vnc.VNCClient();
+	// const connected = client.Connect('acme.com', 5900, 'password');
+	// log(toJSON(connected));
+	// ```
+	VNCClient struct{}
 )
 
+// Connect connects to VNC server using given password.
+// If connection and authentication is successful, it returns true.
+// If connection or authentication is unsuccessful, it returns false and error.
+// The connection is closed after the function returns.
+// @example
+// ```javascript
+// const vnc = require('nuclei/vnc');
+// const client = new vnc.VNCClient();
+// const connected = client.Connect('acme.com', 5900, 'password');
+// ```
+func (c *VNCClient) Connect(ctx context.Context, host string, port int, password string) (bool, error) {
+	executionId := ctx.Value("executionId").(string)
+	return connect(executionId, host, port, password)
+}
+
+// connect attempts to authenticate with a VNC server using the given password
+func connect(executionId string, host string, port int, password string) (bool, error) {
+	if host == "" || port <= 0 {
+		return false, fmt.Errorf("invalid host or port")
+	}
+	if !protocolstate.IsHostAllowed(executionId, host) {
+		// host is not valid according to network policy
+		return false, protocolstate.ErrHostDenied.Msgf(host)
+	}
+
+	dialer := protocolstate.GetDialersWithId(executionId)
+	if dialer == nil {
+		return false, fmt.Errorf("dialers not initialized for %s", executionId)
+	}
+
+	conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port)))
+	if err != nil {
+		return false, err
+	}
+	defer func() {
+		_ = conn.Close()
+	}()
+
+	// Set connection timeout
+	_ = conn.SetDeadline(time.Now().Add(10 * time.Second))
+
+	// Create VNC client config with password
+	vncConfig := vnclib.NewClientConfig(password)
+
+	// Attempt to connect and authenticate
+	c, err := vnclib.Connect(context.TODO(), conn, vncConfig)
+	if err != nil {
+		// Check for specific authentication errors
+		if isAuthError(err) {
+			return false, nil // Authentication failed, but connection succeeded
+		}
+		return false, err // Connection or other error
+	}
+	if c != nil {
+		_ = c.Close()
+	}
+
+	return true, nil
+}
+
+// isAuthError checks if the error is an authentication failure
+func isAuthError(err error) bool {
+	if err == nil {
+		return false
+	}
+
+	// Check for common VNC authentication error messages
+	errStr := err.Error()
+	return stringsutil.ContainsAnyI(errStr, "authentication", "auth", "password", "invalid", "failed")
+}
+
 // IsVNC checks if a host is running a VNC server.
 // It returns a boolean indicating if the host is running a VNC server
 // and the banner of the VNC server.
@@ -57,7 +140,7 @@ func isVNC(executionId string, host string, port int) (IsVNCResponse, error) {
 		_ = conn.Close()
 	}()
 
-	vncPlugin := vnc.VNCPlugin{}
+	vncPlugin := vncplugin.VNCPlugin{}
 	service, err := vncPlugin.Run(conn, timeout, plugins.Target{Host: host})
 	if err != nil {
 		return resp, err
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/reporting/trackers/jira/jira.go b/pkg/reporting/trackers/jira/jira.go
index bfb518da..15ba8565 100644
--- a/pkg/reporting/trackers/jira/jira.go
+++ b/pkg/reporting/trackers/jira/jira.go
@@ -1,16 +1,20 @@
 package jira
 
 import (
+	"bytes"
 	"fmt"
 	"io"
 	"net/http"
 	"net/url"
 	"strings"
 	"sync"
+	"text/template"
 
 	"github.com/andygrunwald/go-jira"
 	"github.com/pkg/errors"
 	"github.com/trivago/tgo/tcontainer"
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
 
 	"github.com/projectdiscovery/gologger"
 	"github.com/projectdiscovery/nuclei/v3/pkg/output"
@@ -25,6 +29,120 @@ type Formatter struct {
 	util.MarkdownFormatter
 }
 
+// TemplateContext holds the data available for template evaluation
+type TemplateContext struct {
+	Severity    string
+	Name        string
+	Host        string
+	CVSSScore   string
+	CVEID       string
+	CWEID       string
+	CVSSMetrics string
+	Tags        []string
+}
+
+// buildTemplateContext creates a template context from a ResultEvent
+func buildTemplateContext(event *output.ResultEvent) *TemplateContext {
+	ctx := &TemplateContext{
+		Host: event.Host,
+		Name: event.Info.Name,
+		Tags: event.Info.Tags.ToSlice(),
+	}
+
+	// Set severity string
+	ctx.Severity = event.Info.SeverityHolder.Severity.String()
+
+	if event.Info.Classification != nil {
+		ctx.CVSSScore = fmt.Sprintf("%.2f", ptr.Safe(event.Info.Classification).CVSSScore)
+		ctx.CVEID = strings.Join(ptr.Safe(event.Info.Classification).CVEID.ToSlice(), ", ")
+		ctx.CWEID = strings.Join(ptr.Safe(event.Info.Classification).CWEID.ToSlice(), ", ")
+		ctx.CVSSMetrics = ptr.Safe(event.Info.Classification).CVSSMetrics
+	}
+
+	return ctx
+}
+
+// evaluateTemplate executes a template string with the given context
+func evaluateTemplate(templateStr string, ctx *TemplateContext) (string, error) {
+	// If no template markers found, return as-is for backward compatibility
+	if !strings.Contains(templateStr, "{{") {
+		return templateStr, nil
+	}
+
+	// Create template with useful functions for JIRA custom fields
+	funcMap := template.FuncMap{
+		"upper":     strings.ToUpper,
+		"lower":     strings.ToLower,
+		"title":     cases.Title(language.English).String,
+		"contains":  strings.Contains,
+		"hasPrefix": strings.HasPrefix,
+		"hasSuffix": strings.HasSuffix,
+		"trim":      strings.Trim,
+		"trimSpace": strings.TrimSpace,
+		"replace":   strings.ReplaceAll,
+		"split":     strings.Split,
+		"join":      strings.Join,
+	}
+
+	tmpl, err := template.New("field").Funcs(funcMap).Parse(templateStr)
+	if err != nil {
+		return templateStr, fmt.Errorf("failed to parse template: %w", err)
+	}
+
+	var buf bytes.Buffer
+	if err := tmpl.Execute(&buf, ctx); err != nil {
+		return templateStr, fmt.Errorf("failed to execute template: %w", err)
+	}
+
+	return buf.String(), nil
+}
+
+// evaluateCustomFieldValue evaluates a custom field value, supporting both new template syntax and legacy $variable syntax
+func (i *Integration) evaluateCustomFieldValue(value string, templateCtx *TemplateContext, event *output.ResultEvent) (interface{}, error) {
+	// Try template evaluation first (supports {{...}} syntax)
+	if strings.Contains(value, "{{") {
+		return evaluateTemplate(value, templateCtx)
+	}
+
+	// Handle legacy $variable syntax for backward compatibility
+	if strings.HasPrefix(value, "$") {
+		variableName := strings.TrimPrefix(value, "$")
+		switch variableName {
+		case "CVSSMetrics":
+			if event.Info.Classification != nil {
+				return ptr.Safe(event.Info.Classification).CVSSMetrics, nil
+			}
+			return "", nil
+		case "CVEID":
+			if event.Info.Classification != nil {
+				return strings.Join(ptr.Safe(event.Info.Classification).CVEID.ToSlice(), ", "), nil
+			}
+			return "", nil
+		case "CWEID":
+			if event.Info.Classification != nil {
+				return strings.Join(ptr.Safe(event.Info.Classification).CWEID.ToSlice(), ", "), nil
+			}
+			return "", nil
+		case "CVSSScore":
+			if event.Info.Classification != nil {
+				return fmt.Sprintf("%.2f", ptr.Safe(event.Info.Classification).CVSSScore), nil
+			}
+			return "", nil
+		case "Host":
+			return event.Host, nil
+		case "Severity":
+			return event.Info.SeverityHolder.Severity.String(), nil
+		case "Name":
+			return event.Info.Name, nil
+		default:
+			return value, nil // return as-is if variable not found
+		}
+	}
+
+	// Return as-is if no template or variable syntax found
+	return value, nil
+}
+
 func (jiraFormatter *Formatter) MakeBold(text string) string {
 	return "*" + text + "*"
 }
@@ -155,12 +273,12 @@ func (i *Integration) CreateNewIssue(event *output.ResultEvent) (*filters.Create
 	if label := i.options.IssueType; label != "" {
 		labels = append(labels, label)
 	}
-	// for each custom value, take the name of the custom field and
-	// set the value of the custom field to the value specified in the
-	// configuration options
+	// Build template context for evaluating custom field templates
+	templateCtx := buildTemplateContext(event)
+
+	// Process custom fields with template evaluation support
 	customFields := tcontainer.NewMarshalMap()
 	for name, value := range i.options.CustomFields {
-		//customFields[name] = map[string]interface{}{"value": value}
 		if valueMap, ok := value.(map[interface{}]interface{}); ok {
 			// Iterate over nested map
 			for nestedName, nestedValue := range valueMap {
@@ -168,32 +286,21 @@ func (i *Integration) CreateNewIssue(event *output.ResultEvent) (*filters.Create
 				if !ok {
 					return nil, fmt.Errorf(`couldn't iterate on nested item "%s": %s`, nestedName, nestedValue)
 				}
-				if strings.HasPrefix(fmtNestedValue, "$") {
-					nestedValue = strings.TrimPrefix(fmtNestedValue, "$")
-					switch nestedValue {
-					case "CVSSMetrics":
-						nestedValue = ptr.Safe(event.Info.Classification).CVSSMetrics
-					case "CVEID":
-						nestedValue = ptr.Safe(event.Info.Classification).CVEID
-					case "CWEID":
-						nestedValue = ptr.Safe(event.Info.Classification).CWEID
-					case "CVSSScore":
-						nestedValue = ptr.Safe(event.Info.Classification).CVSSScore
-					case "Host":
-						nestedValue = event.Host
-					case "Severity":
-						nestedValue = event.Info.SeverityHolder
-					case "Name":
-						nestedValue = event.Info.Name
-					}
+
+				// Evaluate template or handle legacy $variable syntax
+				evaluatedValue, err := i.evaluateCustomFieldValue(fmtNestedValue, templateCtx, event)
+				if err != nil {
+					gologger.Warning().Msgf("Failed to evaluate template for field %s.%s: %v", name, nestedName, err)
+					evaluatedValue = fmtNestedValue // fallback to original value
 				}
+
 				switch nestedName {
 				case "id":
-					customFields[name] = map[string]interface{}{"id": nestedValue}
+					customFields[name] = map[string]interface{}{"id": evaluatedValue}
 				case "name":
-					customFields[name] = map[string]interface{}{"value": nestedValue}
+					customFields[name] = map[string]interface{}{"value": evaluatedValue}
 				case "freeform":
-					customFields[name] = nestedValue
+					customFields[name] = evaluatedValue
 				}
 			}
 		}
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..6e99b7f8 100644
--- a/cmd/integration-test/javascript.go
+++ b/cmd/integration-test/javascript.go
@@ -15,13 +15,17 @@ 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() }},
+	{Path: "protocols/javascript/vnc-pass-brute.yaml", TestCase: &javascriptVncPassBrute{}},
 }
 
 var (
-	redisResource *dockertest.Resource
-	sshResource   *dockertest.Resource
-	pool          *dockertest.Pool
-	defaultRetry  = 3
+	redisResource  *dockertest.Resource
+	sshResource    *dockertest.Resource
+	oracleResource *dockertest.Resource
+	vncResource    *dockertest.Resource
+	pool           *dockertest.Pool
+	defaultRetry   = 3
 )
 
 type javascriptNetHttps struct{}
@@ -98,6 +102,71 @@ 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...)
+}
+
+type javascriptVncPassBrute struct{}
+
+func (j *javascriptVncPassBrute) Execute(filePath string) error {
+	if vncResource == nil || pool == nil {
+		// skip test as vnc is not running
+		return nil
+	}
+	tempPort := vncResource.GetPort("5900/tcp")
+	finalURL := "localhost:" + tempPort
+	defer purge(vncResource)
+	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 +232,41 @@ 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)
+	}
+
+	// setup a temporary vnc server
+	vncResource, err = pool.RunWithOptions(&dockertest.RunOptions{
+		Repository: "dorowu/ubuntu-desktop-lxde-vnc",
+		Tag:        "latest",
+		Env: []string{
+			"VNC_PASSWORD=mysecret",
+		},
+		Platform: "linux/amd64",
+	})
+	if err != nil {
+		log.Printf("Could not start resource: %s", err)
+		return
+	}
+	// by default expire after 30 sec
+	if err := vncResource.Expire(30); err != nil {
+		log.Printf("Could not expire 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/integration_tests/protocols/javascript/vnc-pass-brute.yaml b/integration_tests/protocols/javascript/vnc-pass-brute.yaml
new file mode 100644
index 00000000..68cb9df6
--- /dev/null
+++ b/integration_tests/protocols/javascript/vnc-pass-brute.yaml
@@ -0,0 +1,38 @@
+id: vnc-password-test
+
+info:
+  name: VNC Password Authentication Test
+  author: pdteam
+  severity: high
+  description: |
+    Tests VNC authentication with correct and incorrect passwords.
+  metadata:
+    shodan-query: product:"vnc"
+  tags: js,network,vnc,authentication
+
+javascript:
+  - pre-condition: |
+      isPortOpen(Host,Port)
+
+    code: |
+      let vnc = require('nuclei/vnc');
+      let client = new vnc.VNCClient();
+      client.Connect(Host, Port, Password);
+
+    args:
+      Host: "{{Host}}"
+      Port: "5900"
+      Password: "{{passwords}}"
+    payloads:
+      passwords:
+        - ""
+        - root
+        - password
+        - admin
+        - mysecret
+    stop-at-first-match: true
+      
+    matchers:
+      - type: dsl
+        dsl:
+          - "success == true"
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")
+
+}
diff --git a/pkg/reporting/trackers/jira/jira_test.go b/pkg/reporting/trackers/jira/jira_test.go
index d725a97b..d9b27adf 100644
--- a/pkg/reporting/trackers/jira/jira_test.go
+++ b/pkg/reporting/trackers/jira/jira_test.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/projectdiscovery/nuclei/v3/pkg/model"
 	"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
+	"github.com/projectdiscovery/nuclei/v3/pkg/model/types/stringslice"
 	"github.com/projectdiscovery/nuclei/v3/pkg/output"
 	"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/filters"
 	"github.com/stretchr/testify/require"
@@ -70,3 +71,120 @@ func Test_ShouldFilter_Tracker(t *testing.T) {
 		}}))
 	})
 }
+
+func TestTemplateEvaluation(t *testing.T) {
+	event := &output.ResultEvent{
+		Host: "example.com",
+		Info: model.Info{
+			Name:           "Test vulnerability",
+			SeverityHolder: severity.Holder{Severity: severity.Critical},
+			Classification: &model.Classification{
+				CVSSScore:   9.8,
+				CVEID:       stringslice.StringSlice{Value: []string{"CVE-2023-1234"}},
+				CWEID:       stringslice.StringSlice{Value: []string{"CWE-79"}},
+				CVSSMetrics: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
+			},
+		},
+	}
+
+	integration := &Integration{}
+
+	t.Run("conditional template", func(t *testing.T) {
+		templateStr := `{{if eq .Severity "critical"}}11187{{else if eq .Severity "high"}}11186{{else if eq .Severity "medium"}}11185{{else}}11184{{end}}`
+		result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "11187", result)
+	})
+
+	t.Run("freeform description template", func(t *testing.T) {
+		templateStr := `Vulnerability detected by Nuclei. Name: {{.Name}}, Severity: {{.Severity}}, Host: {{.Host}}`
+		result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		expected := "Vulnerability detected by Nuclei. Name: Test vulnerability, Severity: critical, Host: example.com"
+		require.Equal(t, expected, result)
+	})
+
+	t.Run("legacy variable syntax", func(t *testing.T) {
+		result, err := integration.evaluateCustomFieldValue("$Severity", buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "critical", result)
+
+		result, err = integration.evaluateCustomFieldValue("$Host", buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "example.com", result)
+	})
+
+	t.Run("complex template with conditionals", func(t *testing.T) {
+		templateStr := `{{.Name}} on {{.Host}}
+{{if .CVSSScore}}CVSS: {{.CVSSScore}}{{end}}
+{{if eq .Severity "critical"}}⚠️ CRITICAL{{else}}Standard{{end}}`
+		result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Contains(t, result, "Test vulnerability on example.com")
+		require.Contains(t, result, "CVSS: 9.80")
+		require.Contains(t, result, "⚠️ CRITICAL")
+	})
+
+	t.Run("no template syntax", func(t *testing.T) {
+		result, err := integration.evaluateCustomFieldValue("plain text", buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "plain text", result)
+	})
+
+	t.Run("template functions", func(t *testing.T) {
+		// Test case conversion functions
+		result, err := integration.evaluateCustomFieldValue("{{.Severity | upper}}", buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "CRITICAL", result)
+
+		result, err = integration.evaluateCustomFieldValue("{{.Name | lower}}", buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "test vulnerability", result)
+
+		result, err = integration.evaluateCustomFieldValue("{{.Name | title}}", buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "Test Vulnerability", result)
+
+		// Test string check functions
+		result, err = integration.evaluateCustomFieldValue(`{{if contains .Name "Test"}}has-test{{else}}no-test{{end}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "has-test", result)
+
+		result, err = integration.evaluateCustomFieldValue(`{{if hasPrefix .Host "example"}}starts-with-example{{else}}other{{end}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "starts-with-example", result)
+
+		result, err = integration.evaluateCustomFieldValue(`{{if hasSuffix .Host ".com"}}ends-with-com{{else}}other{{end}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "ends-with-com", result)
+
+		// Test string manipulation functions
+		result, err = integration.evaluateCustomFieldValue(`{{replace .Name " " "-"}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "Test-vulnerability", result)
+
+		result, err = integration.evaluateCustomFieldValue(`{{trimSpace " test "}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "test", result)
+
+		result, err = integration.evaluateCustomFieldValue(`{{trim "...test..." "."}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "test", result)
+
+		// Test split and join functions
+		result, err = integration.evaluateCustomFieldValue(`{{join (split .Name " ") "-"}}`, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Equal(t, "Test-vulnerability", result)
+	})
+
+	t.Run("complex template with functions", func(t *testing.T) {
+		templateStr := `{{.Name | upper}} on {{.Host}}
+{{if contains .Name "SQL"}}SQL-INJECTION{{else if contains .Name "XSS"}}XSS-ATTACK{{else}}OTHER{{end}}
+Priority: {{if eq .Severity "critical"}}{{.Severity | upper}}{{else}}{{.Severity}}{{end}}`
+		result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event)
+		require.NoError(t, err)
+		require.Contains(t, result, "TEST VULNERABILITY on example.com", result)
+		require.Contains(t, result, "OTHER")
+		require.Contains(t, result, "CRITICAL")
+	})
+}