Repository: projectdiscovery/nuclei

Issue:
Template Loading Concurrency Configuration
This issue tracks the changes introduced in PR #6373 to add a new command-line option for controlling concurrent template loading at startup.

**Context:**
- PR: https://github.com/projectdiscovery/nuclei/pull/6373
- Requested by: @Mzack9999

**Summary:**
The PR adds a new `--template-loading-concurrency` (`-tlc`) flag with a default value of 50 to allow users to tune resource usage during template loading. The implementation modifies the template loader to use this configurable concurrency limit instead of a hardcoded value.

**Changes:**
- New CLI flag: `--template-loading-concurrency` (`-tlc`)
- Default value: 50
- Configurable concurrency for template loading operations
- Maintains backward compatibility

Discussion:

Solution patch:
diff --git a/Makefile b/Makefile
index bfb0b5a6..d0d995bf 100644
--- a/Makefile
+++ b/Makefile
@@ -147,8 +147,6 @@ template-validate: build
 template-validate:
 	./bin/nuclei -ut
 	./bin/nuclei -validate \
-		-et .github/ \
-		-et helpers/payloads/ \
 		-et http/technologies \
 		-t dns \
 		-t ssl \
@@ -157,7 +155,5 @@ template-validate:
 		-ept code
 	./bin/nuclei -validate \
 		-w workflows \
-		-et .github/ \
-		-et helpers/payloads/ \
 		-et http/technologies \
 		-ept code
\ No newline at end of file
diff --git a/README.md b/README.md
index 490b6070..de24dc24 100644
--- a/README.md
+++ b/README.md
@@ -286,6 +286,7 @@ RATE-LIMIT:
    -jsc, -js-concurrency int          maximum number of javascript runtimes to be executed in parallel (default 120)
    -pc, -payload-concurrency int      max payload concurrency for each template (default 25)
    -prc, -probe-concurrency int       http probe concurrency with httpx (default 50)
+   -tlc, -template-loading-concurrency int  maximum number of concurrent template loading operations (default 50)
 
 OPTIMIZATIONS:
    -timeout int                     time to wait in seconds before timeout (default 10)
diff --git a/README_CN.md b/README_CN.md
index 99f150e6..5fb4dd14 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -238,6 +238,7 @@ UNCOVER引擎:
    -c, -concurrency int                  并行执行的最大模板数量（默认：25）
    -hbs, -headless-bulk-size int         每个模板并行运行的无头主机最大数量（默认：10）
    -headc, -headless-concurrency int     并行指定无头主机最大数量（默认：10）
+   -tlc, -template-loading-concurrency int  最大并发模板加载操作数（默认：50）
 
 
 优化：
diff --git a/README_ES.md b/README_ES.md
index 27f60ee8..ec7949ef 100644
--- a/README_ES.md
+++ b/README_ES.md
@@ -244,6 +244,7 @@ RATE-LIMIT:
    -headc, -headless-concurrency int  número máximo de plantillas headless a ejecutar en paralelo (por defecto 10)
    -jsc, -js-concurrency int          número máximo de entornos de ejecución de JavaScript a ejecutar en paralelo (por defecto 120)
    -pc, -payload-concurrency int      concurrencia máxima de carga útil para cada plantilla (por defecto 25)
+   -tlc, -template-loading-concurrency int  número máximo de operaciones de carga de plantillas concurrentes (por defecto 50)
 
 OPTIMIZATIONS:
    -timeout int                     tiempo de espera en segundos (por defecto 10)
diff --git a/README_ID.md b/README_ID.md
index 05c163c2..459352b4 100644
--- a/README_ID.md
+++ b/README_ID.md
@@ -211,6 +211,7 @@ RATE-LIMIT:
    -c, -concurrency int               maximum number of templates to be executed in parallel (default 25)
    -hbs, -headless-bulk-size int      maximum number of headless hosts to be analyzed in parallel per template (default 10)
    -headc, -headless-concurrency int  maximum number of headless templates to be executed in parallel (default 10)
+   -tlc, -template-loading-concurrency int  maximum number of concurrent template loading operations (default 50)
 
 OPTIMIZATIONS:
    -timeout int                        time to wait in seconds before timeout (default 10)
diff --git a/README_KR.md b/README_KR.md
index 6181c866..d0828564 100644
--- a/README_KR.md
+++ b/README_KR.md
@@ -209,6 +209,7 @@ RATE-LIMIT:
    -c, -concurrency int               병렬로 실행할 최대 템플릿 수 (기본값 25)
    -hbs, -headless-bulk-size int      템플릿당 병렬로 분석할 최대 headless 호스트 수 (기본값 10)
    -headc, -headless-concurrency int  병렬로 실행할 최대 headless 템플릿 수 (기본값 10)
+   -tlc, -template-loading-concurrency int  최대 동시 템플릿 로딩 작업 수 (기본값 50)
 
 OPTIMIZATIONS:
    -timeout int                     타임아웃 전에 기다릴 초 수 (기본값 10)
diff --git a/README_PT-BR.md b/README_PT-BR.md
index 012f878f..e63a3d8a 100644
--- a/README_PT-BR.md
+++ b/README_PT-BR.md
@@ -244,6 +244,7 @@ RATE-LIMIT:
    -headc, -headless-concurrency int  número máximo de templates headless a serem executados em paralelo (padrão 10)
    -jsc, -js-concurrency int          número máximo de ambientes de execução de JavaScript a serem executados em paralelo (padrão 120)
    -pc, -payload-concurrency int      concorrência máxima de payload para cada template (padrão 25)
+   -tlc, -template-loading-concurrency int  número máximo de operações de carregamento de templates concorrentes (padrão 50)
 
 OPTIMIZATIONS:
    -timeout int                     tempo limite em segundos (padrão 10)
diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go
index c08f52bf..188d3fba 100644
--- a/cmd/nuclei/main.go
+++ b/cmd/nuclei/main.go
@@ -411,6 +411,7 @@ on extensive configurability, massive extensibility and ease of use.`)
 		flagSet.IntVarP(&options.JsConcurrency, "js-concurrency", "jsc", 120, "maximum number of javascript runtimes to be executed in parallel"),
 		flagSet.IntVarP(&options.PayloadConcurrency, "payload-concurrency", "pc", 25, "max payload concurrency for each template"),
 		flagSet.IntVarP(&options.ProbeConcurrency, "probe-concurrency", "prc", 50, "http probe concurrency with httpx"),
+		flagSet.IntVarP(&options.TemplateLoadingConcurrency, "template-loading-concurrency", "tlc", types.DefaultTemplateLoadingConcurrency, "maximum number of concurrent template loading operations"),
 	)
 	flagSet.CreateGroup("optimization", "Optimizations",
 		flagSet.IntVar(&options.Timeout, "timeout", 10, "time to wait in seconds before timeout"),
diff --git a/go.mod b/go.mod
index 0acd105f..121db220 100644
--- a/go.mod
+++ b/go.mod
@@ -18,16 +18,16 @@ require (
 	github.com/json-iterator/go v1.1.12
 	github.com/julienschmidt/httprouter v1.3.0
 	github.com/logrusorgru/aurora v2.0.3+incompatible
-	github.com/miekg/dns v1.1.66
+	github.com/miekg/dns v1.1.68
 	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.11
-	github.com/projectdiscovery/hmap v0.0.94
+	github.com/projectdiscovery/fastdialer v0.4.12
+	github.com/projectdiscovery/hmap v0.0.95
 	github.com/projectdiscovery/interactsh v1.2.4
 	github.com/projectdiscovery/rawhttp v0.1.90
-	github.com/projectdiscovery/retryabledns v1.0.107
-	github.com/projectdiscovery/retryablehttp-go v1.0.126
+	github.com/projectdiscovery/retryabledns v1.0.108
+	github.com/projectdiscovery/retryablehttp-go v1.0.127
 	github.com/projectdiscovery/yamldoc-go v1.0.6
 	github.com/remeh/sizedwaitgroup v1.0.0
 	github.com/rs/xid v1.6.0
@@ -91,26 +91,26 @@ 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.7.1
+	github.com/projectdiscovery/dsl v0.7.2
 	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
 	github.com/projectdiscovery/goflags v0.1.74
-	github.com/projectdiscovery/gologger v1.1.56
+	github.com/projectdiscovery/gologger v1.1.57
 	github.com/projectdiscovery/gostruct v0.0.2
 	github.com/projectdiscovery/gozero v0.1.0
 	github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a
 	github.com/projectdiscovery/mapcidr v1.1.95
 	github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
-	github.com/projectdiscovery/networkpolicy v0.1.25
+	github.com/projectdiscovery/networkpolicy v0.1.26
 	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/useragent v0.0.102
 	github.com/projectdiscovery/utils v0.6.0
-	github.com/projectdiscovery/wappalyzergo v0.2.48
+	github.com/projectdiscovery/wappalyzergo v0.2.49
 	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
@@ -189,7 +189,7 @@ require (
 	github.com/cloudflare/cfssl v1.6.4 // indirect
 	github.com/cloudflare/circl v1.6.1 // indirect
 	github.com/cloudwego/base64x v0.1.5 // indirect
-	github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
+	github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a // indirect
 	github.com/containerd/continuity v0.4.5 // indirect
 	github.com/containerd/errdefs v1.0.0 // indirect
 	github.com/containerd/errdefs/pkg v0.3.0 // indirect
@@ -318,7 +318,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.2.3 // indirect
+	github.com/projectdiscovery/cdncheck v1.2.4 // 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
@@ -335,7 +335,7 @@ require (
 	github.com/tidwall/buntdb v1.3.1 // indirect
 	github.com/tidwall/gjson v1.18.0 // indirect
 	github.com/tidwall/grect v0.1.4 // indirect
-	github.com/tidwall/match v1.1.1 // indirect
+	github.com/tidwall/match v1.2.0 // indirect
 	github.com/tidwall/pretty v1.2.1 // indirect
 	github.com/tidwall/rtred v0.1.2 // indirect
 	github.com/tidwall/tinyqueue v0.1.1 // indirect
@@ -394,11 +394,11 @@ require (
 	go.uber.org/zap v1.27.0 // indirect
 	goftp.io/server/v2 v2.0.1 // indirect
 	golang.org/x/crypto v0.42.0 // indirect
-	golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
-	golang.org/x/mod v0.27.0 // indirect
+	golang.org/x/exp v0.0.0-20250911091902-df9299821621
+	golang.org/x/mod v0.28.0 // indirect
 	golang.org/x/sys v0.36.0 // indirect
 	golang.org/x/time v0.11.0 // indirect
-	golang.org/x/tools v0.36.0
+	golang.org/x/tools v0.37.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 d8dd43e9..408202c2 100644
--- a/go.sum
+++ b/go.sum
@@ -554,8 +554,8 @@ github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWH
 github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
 github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM=
 github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
-github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
-github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
+github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a h1:Ohw57yVY2dBTt+gsC6aZdteyxwlxfbtgkFEMTEkwgSw=
+github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
 github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
 github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
 github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -1132,8 +1132,8 @@ github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB
 github.com/microsoft/go-mssqldb v1.9.2 h1:nY8TmFMQOHpm2qVWo6y4I2mAmVdZqlGiMGAYt64Ibbs=
 github.com/microsoft/go-mssqldb v1.9.2/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA=
 github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
-github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
-github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
+github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
+github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
 github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0=
 github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc=
 github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
@@ -1249,14 +1249,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.2.3 h1:AM0wfoB7UW2J9c9OFOZCJXooem5kjh22YP/KK5wkUnE=
-github.com/projectdiscovery/cdncheck v1.2.3/go.mod h1:B3sOVVsr1KJ6x+KkBWqWlpNDSsK51SAhB7mpw2vxgp4=
+github.com/projectdiscovery/cdncheck v1.2.4 h1:j2bd6h2aFGLkgKwfMLhheoZgTIIVabL886zhClRZx/U=
+github.com/projectdiscovery/cdncheck v1.2.4/go.mod h1:NDm/+PwVnC8ishg3SY/DEe8uzeSdvRjsHtF0pSKXxSA=
 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.7.1 h1:KbMkZS/R8i6ZWs/9ycA0otzWilFIF4hyPtt3R63JY9U=
-github.com/projectdiscovery/dsl v0.7.1/go.mod h1:9OqJnKhtgtgs180Gk5vsWQN2NhKR3gGnDOKXkfsNks4=
-github.com/projectdiscovery/fastdialer v0.4.11 h1:6JYoORInQiENFPTqGMI+1GaL5hOTD/sjWrSbzM8d+Z0=
-github.com/projectdiscovery/fastdialer v0.4.11/go.mod h1:i2dB26BHw0BMrx7ccbHcb/1LE5q9gy0ojvBytATl38E=
+github.com/projectdiscovery/dsl v0.7.2 h1:2yszHrd/2Jut1Fa3jG04H5Gvz0WE5vSADNindox0fIA=
+github.com/projectdiscovery/dsl v0.7.2/go.mod h1:UCkWl+NtZnPLQ6y2L/FwDcJzQm78HY5BHmJ8E7HMGSQ=
+github.com/projectdiscovery/fastdialer v0.4.12 h1:5lHnx1SK8HRF4xoxlbRMytd3r0jwvw6aObPj9xw+Q5s=
+github.com/projectdiscovery/fastdialer v0.4.12/go.mod h1:SFhDHNw7VjSoefZfJeR4vqmhKOExPSGPZud2TeeUG50=
 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=
@@ -1267,14 +1267,14 @@ github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG90
 github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY=
 github.com/projectdiscovery/goflags v0.1.74 h1:n85uTRj5qMosm0PFBfsvOL24I7TdWRcWq/1GynhXS7c=
 github.com/projectdiscovery/goflags v0.1.74/go.mod h1:UMc9/7dFz2oln+10tv6cy+7WZKTHf9UGhaNkF95emh4=
-github.com/projectdiscovery/gologger v1.1.56 h1:XZCJs534F0pTaHToQWtqCrAzUJwaF572qLzrSn5adOA=
-github.com/projectdiscovery/gologger v1.1.56/go.mod h1:RtAcBG7KzTWmAEVEVWiBbKGKsYpqzxKXzn3yhAFkfic=
+github.com/projectdiscovery/gologger v1.1.57 h1:pVmhSeGeBlgX/Vgjulu2GhrCK6oLfgHBQtarmgFMftM=
+github.com/projectdiscovery/gologger v1.1.57/go.mod h1:8FJFKmo0N4ITIH3n1Jy4ze6ijr+mA3t78g+VpN8uBRU=
 github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M=
 github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
 github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mnag8zXIAQI=
 github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs=
-github.com/projectdiscovery/hmap v0.0.94 h1:Q2/89U2rkDVz59j/WBzaRPmpRrYamDWnzQgauk+K03E=
-github.com/projectdiscovery/hmap v0.0.94/go.mod h1:QtqZlGUwq3/SNiwEfArayfwrZU4g0/tpw6lJlxP1XEI=
+github.com/projectdiscovery/hmap v0.0.95 h1:OO6MCySlK2xMzvJmsYUwdaI7YWv/U437OtsN0Ovw72k=
+github.com/projectdiscovery/hmap v0.0.95/go.mod h1:KiTRdGd/GzX7uaoFWPrPBxPf4X/uZ9HTQ9dQ8x7x1bo=
 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=
@@ -1287,18 +1287,18 @@ github.com/projectdiscovery/mapcidr v1.1.95 h1:SHbVanfeTkqCQ6WX/iYa1q8IlfgrPAubw
 github.com/projectdiscovery/mapcidr v1.1.95/go.mod h1:ykv6dnTPeU+tigZjonpO8VG6UYieZbfIOtkRft3ynr8=
 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.25 h1:2f3Nxp4ncz/95hm6PkIDLcjMJI6ei2YsgkQ29NZn7b0=
-github.com/projectdiscovery/networkpolicy v0.1.25/go.mod h1:6zQPoZRyGeNq0WvWnL5cbah3mCg9KJiOn5tgVQWGIn4=
+github.com/projectdiscovery/networkpolicy v0.1.26 h1:RxZJoOyDM/Ru4GNHmrlsjBHqWz0TFMchK35S2W3Suw8=
+github.com/projectdiscovery/networkpolicy v0.1.26/go.mod h1:wC25awxBHp9y4o30hMeSobFaMHw+gWlcy55tL3Z84fM=
 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.107 h1:Rd1JK7hfL68xRg3RzXmw9Q6B6WSNv9bdPhUoGvvebyg=
-github.com/projectdiscovery/retryabledns v1.0.107/go.mod h1:XddeOhDpwS0qR8/T4GXRGgDQsLhtRHw3TRdMsgJs28o=
-github.com/projectdiscovery/retryablehttp-go v1.0.126 h1:kf48eEv1LIzK7qK+tpb4WkmPOkv09L83ndUe65MU+pA=
-github.com/projectdiscovery/retryablehttp-go v1.0.126/go.mod h1:PxOnqvh/v6e/qNiKE/gCzqB3Hn5io/57GH/JPUPLoT4=
+github.com/projectdiscovery/retryabledns v1.0.108 h1:47LYRW2LY/0cDnZQfUhoOHNxe9rNc9NQ9ZfNrV/GbyM=
+github.com/projectdiscovery/retryabledns v1.0.108/go.mod h1:j7H7K6JZePh9PeNleeRUtDSrkUKMpwDhZw3Ogewzio8=
+github.com/projectdiscovery/retryablehttp-go v1.0.127 h1:CzEkkWZXb48D8Vy1SvBZF/qjbjp5ILYMHE5M+T/xdf8=
+github.com/projectdiscovery/retryablehttp-go v1.0.127/go.mod h1:9OOZjJuo+2v5RCGvk1lLqt6lctNxLPzldb0yJOMoqR8=
 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=
@@ -1307,12 +1307,12 @@ github.com/projectdiscovery/tlsx v1.2.1 h1:R8QgKb/vxd6Y0cfGFBYs4nn0zodHABeeLPqJj
 github.com/projectdiscovery/tlsx v1.2.1/go.mod h1:p19UHGQ6bvcbvhO4NvYBKOxlE4QvrUaectx9g/Mm3JA=
 github.com/projectdiscovery/uncover v1.1.0 h1:UDp/qLZn78YZb6VPoOrfyP1vz+ojEx8VrTTyjjRt9UU=
 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/useragent v0.0.102 h1:Xfr8a7LQhIu0zeSz5gBxGCdyuqZbhkOMAEQUcEZXyBU=
+github.com/projectdiscovery/useragent v0.0.102/go.mod h1:DIfLRBKZ6dLhHRnMYkxdg6Jpu0kpE3pJlMG94dsIchY=
 github.com/projectdiscovery/utils v0.6.0 h1:rH4Haei7uHgqEq6pFGe8U+iD4PoBWUDB8LhoNxPawkk=
 github.com/projectdiscovery/utils v0.6.0/go.mod h1:NT7ExqILrDukgBFPPLBKQzSKYMBfecNcab7jT1bakRE=
-github.com/projectdiscovery/wappalyzergo v0.2.48 h1:bsNfmVTySLp9kHc1mO3+bxyclXY7hdpbQeU7WVfo4Us=
-github.com/projectdiscovery/wappalyzergo v0.2.48/go.mod h1:kPzB+L3ISGO5m8u5fukjlF5FJFJ1NLV86emOx+k3AVU=
+github.com/projectdiscovery/wappalyzergo v0.2.49 h1:hOoAzNoJ7R9mefy4HU3JKeJDzXSTGjRCCqoJAwebG+8=
+github.com/projectdiscovery/wappalyzergo v0.2.49/go.mod h1:kPzB+L3ISGO5m8u5fukjlF5FJFJ1NLV86emOx+k3AVU=
 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=
@@ -1458,8 +1458,9 @@ github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=
 github.com/tidwall/grect v0.1.4/go.mod h1:9FBsaYRaR0Tcy4UwefBX/UDcDcDy9V5jUcxHzv2jd5Q=
 github.com/tidwall/lotsa v1.0.2 h1:dNVBH5MErdaQ/xd9s769R31/n2dXavsQ0Yf4TMEHHw8=
 github.com/tidwall/lotsa v1.0.2/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UMuqgR8=
-github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
 github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
+github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
 github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
 github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
@@ -1714,8 +1715,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
 golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
-golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
-golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
+golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
+golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1765,8 +1766,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.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
-golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
+golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
+golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
 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=
@@ -2169,8 +2170,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.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
-golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
+golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
+golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
 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/config/template.go b/pkg/catalog/config/template.go
index 3d7b33de..2f799918 100644
--- a/pkg/catalog/config/template.go
+++ b/pkg/catalog/config/template.go
@@ -12,7 +12,10 @@ import (
 	stringsutil "github.com/projectdiscovery/utils/strings"
 )
 
-var knownConfigFiles = []string{"cves.json", "contributors.json", "TEMPLATES-STATS.json"}
+var (
+	knownConfigFiles     = []string{"cves.json", "contributors.json", "TEMPLATES-STATS.json"}
+	knownMiscDirectories = []string{".git", ".github", "helpers"}
+)
 
 // TemplateFormat
 type TemplateFormat uint8
@@ -23,6 +26,25 @@ const (
 	Unknown
 )
 
+// GetKnownConfigFiles returns known config files.
+func GetKnownConfigFiles() []string {
+	return knownConfigFiles
+}
+
+// GetKnownMiscDirectories returns known misc directories with trailing slashes.
+//
+// The trailing slash ensures that directory matching is explicit and avoids
+// falsely match files with similar names (e.g. "helpers" matching
+// "some-helpers.yaml"), since [IsTemplate] checks against normalized full paths.
+func GetKnownMiscDirectories() []string {
+	trailedSlashDirs := make([]string, 0, len(knownMiscDirectories))
+	for _, dir := range knownMiscDirectories {
+		trailedSlashDirs = append(trailedSlashDirs, dir+string(os.PathSeparator))
+	}
+
+	return trailedSlashDirs
+}
+
 // GetTemplateFormatFromExt returns template format
 func GetTemplateFormatFromExt(filePath string) TemplateFormat {
 	fileExt := strings.ToLower(filepath.Ext(filePath))
@@ -41,13 +63,22 @@ func GetSupportTemplateFileExtensions() []string {
 	return []string{extensions.YAML, extensions.JSON}
 }
 
-// IsTemplate is a callback function used by goflags to decide if given file should be read
-// if it is not a nuclei-template file only then file is read
-func IsTemplate(filename string) bool {
-	if stringsutil.ContainsAny(filename, knownConfigFiles...) {
+// IsTemplate returns true if the file is a template based on its path.
+// It used by goflags and other places to filter out non-template files.
+func IsTemplate(fpath string) bool {
+	fpath = filepath.FromSlash(fpath)
+	fname := filepath.Base(fpath)
+	fext := strings.ToLower(filepath.Ext(fpath))
+
+	if stringsutil.ContainsAny(fname, GetKnownConfigFiles()...) {
+		return false
+	}
+
+	if stringsutil.ContainsAny(fpath, GetKnownMiscDirectories()...) {
 		return false
 	}
-	return stringsutil.EqualFoldAny(filepath.Ext(filename), GetSupportTemplateFileExtensions()...)
+
+	return stringsutil.EqualFoldAny(fext, GetSupportTemplateFileExtensions()...)
 }
 
 type template struct {
diff --git a/pkg/catalog/disk/find.go b/pkg/catalog/disk/find.go
index 7a70c1bc..0a89ba54 100644
--- a/pkg/catalog/disk/find.go
+++ b/pkg/catalog/disk/find.go
@@ -257,7 +257,7 @@ func (c *DiskCatalog) findDirectoryMatches(absPath string, processed map[string]
 				if err != nil {
 					return nil
 				}
-				if !d.IsDir() && config.GetTemplateFormatFromExt(path) != config.Unknown {
+				if !d.IsDir() && config.IsTemplate(path) {
 					if _, ok := processed[path]; !ok {
 						results = append(results, path)
 						processed[path] = struct{}{}
@@ -281,7 +281,7 @@ func (c *DiskCatalog) findDirectoryMatches(absPath string, processed map[string]
 				if err != nil {
 					return nil
 				}
-				if !d.IsDir() && config.GetTemplateFormatFromExt(path) != config.Unknown {
+				if !d.IsDir() && config.IsTemplate(path) {
 					if _, ok := processed[path]; !ok {
 						results = append(results, path)
 						processed[path] = struct{}{}
diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go
index b1887149..1a8fe574 100644
--- a/pkg/catalog/loader/loader.go
+++ b/pkg/catalog/loader/loader.go
@@ -524,7 +524,11 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
 		}
 	}
 
-	wgLoadTemplates, errWg := syncutil.New(syncutil.WithSize(50))
+	concurrency := store.config.ExecutorOptions.Options.TemplateLoadingConcurrency
+	if concurrency <= 0 {
+		concurrency = types.DefaultTemplateLoadingConcurrency
+	}
+	wgLoadTemplates, errWg := syncutil.New(syncutil.WithSize(concurrency))
 	if errWg != nil {
 		panic("could not create wait group")
 	}
diff --git a/pkg/templates/workflows.go b/pkg/templates/workflows.go
index 50029af1..2f1881cb 100644
--- a/pkg/templates/workflows.go
+++ b/pkg/templates/workflows.go
@@ -94,7 +94,14 @@ func parseWorkflowTemplate(workflow *workflows.WorkflowTemplate, preprocessor Pr
 
 		if len(template.RequestsCode) > 0 {
 			if !options.Options.EnableCodeTemplates {
-				gologger.Warning().Msgf("`-code` flag not found, skipping code template from workflow: %v\n", path)
+				// NOTE(dwisiswant0): It is safe to continue here during
+				// validation mode, because the template has already been parsed
+				// and syntax-validated by templates.Parse() above. It only
+				// prevents adding to workflow's executer list and suppresses
+				// warning messages.
+				if !options.Options.Validate {
+					gologger.Warning().Msgf("`-code` flag not found, skipping code template from workflow: %v\n", path)
+				}
 				continue
 			} else if !template.Verified {
 				// unverfied code templates are not allowed in workflows
diff --git a/pkg/types/types.go b/pkg/types/types.go
index 26e98ba6..08ed924f 100644
--- a/pkg/types/types.go
+++ b/pkg/types/types.go
@@ -20,6 +20,8 @@ import (
 	unitutils "github.com/projectdiscovery/utils/unit"
 )
 
+const DefaultTemplateLoadingConcurrency = 50
+
 var (
 	// ErrNoMoreRequests is internal error to indicate that generator has no more requests to generate
 	ErrNoMoreRequests = io.EOF
@@ -429,6 +431,8 @@ type Options struct {
 	PayloadConcurrency int
 	// ProbeConcurrency is the number of concurrent http probes to run with httpx
 	ProbeConcurrency int
+	// TemplateLoadingConcurrency is the number of concurrent template loading operations
+	TemplateLoadingConcurrency int
 	// Dast only runs DAST templates
 	DAST bool
 	// DASTServer is the flag to start nuclei as a DAST server
@@ -775,19 +779,20 @@ func (options *Options) HasClientCertificates() bool {
 // DefaultOptions returns default options for nuclei
 func DefaultOptions() *Options {
 	return &Options{
-		RateLimit:               150,
-		RateLimitDuration:       time.Second,
-		BulkSize:                25,
-		TemplateThreads:         25,
-		HeadlessBulkSize:        10,
-		PayloadConcurrency:      25,
-		HeadlessTemplateThreads: 10,
-		ProbeConcurrency:        50,
-		Timeout:                 5,
-		Retries:                 1,
-		MaxHostError:            30,
-		ResponseReadSize:        10 * unitutils.Mega,
-		ResponseSaveSize:        unitutils.Mega,
+		RateLimit:                  150,
+		RateLimitDuration:          time.Second,
+		BulkSize:                   25,
+		TemplateThreads:            25,
+		HeadlessBulkSize:           10,
+		PayloadConcurrency:         25,
+		HeadlessTemplateThreads:    10,
+		ProbeConcurrency:           50,
+		TemplateLoadingConcurrency: DefaultTemplateLoadingConcurrency,
+		Timeout:                    5,
+		Retries:                    1,
+		MaxHostError:               30,
+		ResponseReadSize:           10 * unitutils.Mega,
+		ResponseSaveSize:           unitutils.Mega,
 	}
 }
 
diff --git a/pkg/utils/http_probe.go b/pkg/utils/http_probe.go
index 9e3046fe..3cc7d5d0 100644
--- a/pkg/utils/http_probe.go
+++ b/pkg/utils/http_probe.go
@@ -2,22 +2,46 @@ package utils
 
 import (
 	"fmt"
+	"net"
 	"net/http"
 
 	"github.com/projectdiscovery/httpx/common/httpx"
 	"github.com/projectdiscovery/nuclei/v3/pkg/input/types"
 	"github.com/projectdiscovery/useragent"
+	sliceutil "github.com/projectdiscovery/utils/slice"
 )
 
-var (
-	HttpSchemes = []string{"https", "http"}
-)
+var commonHttpPorts = []string{
+	"80",
+	"8080",
+}
+var defaultHttpSchemes = []string{
+	"https",
+	"http",
+}
+var httpFirstSchemes = []string{
+	"http",
+	"https",
+}
+
+// determineSchemeOrder for the input
+func determineSchemeOrder(input string) []string {
+	// if input has port that is commonly used for HTTP, return http then https
+	if _, port, err := net.SplitHostPort(input); err == nil {
+		if sliceutil.Contains(commonHttpPorts, port) {
+			return httpFirstSchemes
+		}
+	}
+
+	return defaultHttpSchemes
+}
 
-// ProbeURL probes the scheme for a URL. first HTTPS is tried
-// and if any errors occur http is tried. If none succeeds, probing
-// is abandoned for such URLs.
+// ProbeURL probes the scheme for a URL.
+// http schemes are selected with heuristics
+// If none succeeds, probing is abandoned for such URLs.
 func ProbeURL(input string, httpxclient *httpx.HTTPX) string {
-	for _, scheme := range HttpSchemes {
+	schemes := determineSchemeOrder(input)
+	for _, scheme := range schemes {
 		formedURL := fmt.Sprintf("%s://%s", scheme, input)
 		req, err := httpxclient.NewRequest(http.MethodHead, formedURL)
 		if err != nil {
@@ -39,7 +63,7 @@ type inputLivenessChecker struct {
 	client *httpx.HTTPX
 }
 
-// ProbeURL probes the scheme for a URL. first HTTPS is tried
+// ProbeURL probes the scheme for a URL.
 func (i *inputLivenessChecker) ProbeURL(input string) (string, error) {
 	return ProbeURL(input, i.client), nil
 }



Test patch:
diff --git a/pkg/utils/http_probe_test.go b/pkg/utils/http_probe_test.go
new file mode 100644
index 00000000..f000a8a8
--- /dev/null
+++ b/pkg/utils/http_probe_test.go
@@ -0,0 +1,37 @@
+package utils
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestDetermineSchemeOrder(t *testing.T) {
+	type testCase struct {
+		input    string
+		expected []string
+	}
+
+	tests := []testCase{
+		// No port or uncommon ports should return https first
+		{"example.com", []string{"https", "http"}},
+		{"example.com:443", []string{"https", "http"}},
+		{"127.0.0.1", []string{"https", "http"}},
+		{"[fe80::1]:443", []string{"https", "http"}},
+		// Common HTTP ports should return http first
+		{"example.com:80", []string{"http", "https"}},
+		{"example.com:8080", []string{"http", "https"}},
+		{"127.0.0.1:80", []string{"http", "https"}},
+		{"127.0.0.1:8080", []string{"http", "https"}},
+		{"fe80::1", []string{"https", "http"}},
+		{"[fe80::1]:80", []string{"http", "https"}},
+		{"[fe80::1]:8080", []string{"http", "https"}},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.input, func(t *testing.T) {
+			actual := determineSchemeOrder(tc.input)
+			require.Equal(t, tc.expected, actual)
+		})
+	}
+}