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