diff --git a/README.md b/README.md
index 741ceafc3..490b60709 100644
--- a/README.md
+++ b/README.md
@@ -356,6 +356,7 @@ CLOUD:
AUTHENTICATION:
-sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan
-ps, -prefetch-secrets prefetch secrets from the secrets file
+ # NOTE: Headers in secrets files preserve exact casing (useful for case-sensitive APIs)
EXAMPLES:
diff --git a/SYNTAX-REFERENCE.md b/SYNTAX-REFERENCE.md
index 24cbd04d3..399c25a93 100755
--- a/SYNTAX-REFERENCE.md
+++ b/SYNTAX-REFERENCE.md
@@ -1194,6 +1194,8 @@ be provided as payload which will be read on run-time.
Headers contains HTTP Headers to send with the request.
+**Note:** When using headers in authentication secrets files (via `-sf` flag), header names preserve exact casing (e.g., `barAuthToken` stays as `barAuthToken`). This is useful for APIs that require case-sensitive header names. Template headers are canonicalized by default.
+
Examples:
@@ -1424,6 +1426,8 @@ Valid values:
SkipSecretFile skips the authentication or authorization configured in the secret file.
+**Note:** Authentication secrets files preserve exact header casing, which is useful for case-sensitive APIs.
+
diff --git a/pkg/authprovider/authx/file.go b/pkg/authprovider/authx/file.go
index 804b6c340..655039b9e 100644
--- a/pkg/authprovider/authx/file.go
+++ b/pkg/authprovider/authx/file.go
@@ -55,7 +55,7 @@ type Secret struct {
Type string `json:"type" yaml:"type"`
Domains []string `json:"domains" yaml:"domains"`
DomainsRegex []string `json:"domains-regex" yaml:"domains-regex"`
- Headers []KV `json:"headers" yaml:"headers"`
+ Headers []KV `json:"headers" yaml:"headers"` // Headers preserve exact casing (useful for case-sensitive APIs)
Cookies []Cookie `json:"cookies" yaml:"cookies"`
Params []KV `json:"params" yaml:"params"`
Username string `json:"username" yaml:"username"` // can be either email or username
@@ -148,7 +148,7 @@ func (s *Secret) Validate() error {
}
type KV struct {
- Key string `json:"key" yaml:"key"`
+ Key string `json:"key" yaml:"key"` // Header key (preserves exact casing)
Value string `json:"value" yaml:"value"`
}
diff --git a/pkg/authprovider/authx/headers_auth.go b/pkg/authprovider/authx/headers_auth.go
index b3ede114d..d474f75bd 100644
--- a/pkg/authprovider/authx/headers_auth.go
+++ b/pkg/authprovider/authx/headers_auth.go
@@ -21,15 +21,19 @@ func NewHeadersAuthStrategy(data *Secret) *HeadersAuthStrategy {
}
// Apply applies the headers auth strategy to the request
+// NOTE: This preserves exact header casing (e.g., barAuthToken stays as barAuthToken)
+// This is useful for APIs that require case-sensitive header names
func (s *HeadersAuthStrategy) Apply(req *http.Request) {
for _, header := range s.Data.Headers {
- req.Header.Set(header.Key, header.Value)
+ req.Header[header.Key] = []string{header.Value}
}
}
// ApplyOnRR applies the headers auth strategy to the retryable request
+// NOTE: This preserves exact header casing (e.g., barAuthToken stays as barAuthToken)
+// This is useful for APIs that require case-sensitive header names
func (s *HeadersAuthStrategy) ApplyOnRR(req *retryablehttp.Request) {
for _, header := range s.Data.Headers {
- req.Header.Set(header.Key, header.Value)
+ req.Header[header.Key] = []string{header.Value}
}
}
diff --git a/pkg/authprovider/authx/testData/example-auth.yaml b/pkg/authprovider/authx/testData/example-auth.yaml
index 0c3175090..0f64a2798 100644
--- a/pkg/authprovider/authx/testData/example-auth.yaml
+++ b/pkg/authprovider/authx/testData/example-auth.yaml
@@ -12,6 +12,8 @@ info:
# static secrets
static:
# for header based auth session
+ # NOTE: Headers preserve exact casing (e.g., x-pdcp-key stays as x-pdcp-key)
+ # This is useful for APIs that require case-sensitive header names
- type: header
domains:
- api.projectdiscovery.io
@@ -20,6 +22,8 @@ static:
headers:
- key: x-pdcp-key
value:
+ - key: barAuthToken
+ value:
# for query based auth session
- type: Query