Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 40 additions & 6 deletions pkg/protocols/headless/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import (

// Browser is a browser structure for nuclei headless module
type Browser struct {
customAgent string
tempDir string
previousPIDs map[int32]struct{} // track already running PIDs
engine *rod.Browser
options *types.Options
launcher *launcher.Launcher
customAgent string
defaultHeaders map[string]string
tempDir string
previousPIDs map[int32]struct{} // track already running PIDs
engine *rod.Browser
options *types.Options
launcher *launcher.Launcher

// use getHTTPClient to get the http client
httpClient *http.Client
Expand Down Expand Up @@ -95,6 +96,7 @@ func New(options *types.Options) (*Browser, error) {
if browserErr := browser.Connect(); browserErr != nil {
return nil, browserErr
}
defaultHeaders := make(map[string]string)
customAgent := ""
for _, option := range options.CustomHeaders {
parts := strings.SplitN(option, ":", 2)
Expand All @@ -103,12 +105,20 @@ func New(options *types.Options) (*Browser, error) {
}
if strings.EqualFold(parts[0], "User-Agent") {
customAgent = parts[1]
} else {
k := strings.TrimSpace(parts[0])
v := strings.TrimSpace(parts[1])
if k == "" || v == "" {
continue
}
defaultHeaders[k] = v
}
}

engine := &Browser{
tempDir: dataStore,
customAgent: customAgent,
defaultHeaders: defaultHeaders,
engine: browser,
options: options,
httpClientOnce: &sync.Once{},
Expand All @@ -135,6 +145,30 @@ func (b *Browser) UserAgent() string {
return b.customAgent
}

// applyDefaultHeaders setsheaders passed via cli -H flag
func (b *Browser) applyDefaultHeaders(p *rod.Page) error {
pairs := make([]string, 0, len(b.defaultHeaders)*2+2)

hasAcceptLanguage := false
for k := range b.defaultHeaders {
if strings.EqualFold(k, "Accept-Language") {
hasAcceptLanguage = true
break
}
}
if !hasAcceptLanguage {
pairs = append(pairs, "Accept-Language", "en, en-GB, en-us;")
}
for k, v := range b.defaultHeaders {
pairs = append(pairs, k, v)
}
if len(pairs) == 0 {
return nil
}
_, err := p.SetExtraHeaders(pairs)
return err
}

func (b *Browser) getHTTPClient() (*http.Client, error) {
var err error
b.httpClientOnce.Do(func() {
Expand Down
8 changes: 4 additions & 4 deletions pkg/protocols/headless/engine/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map
}
page = page.Timeout(options.Timeout)

if err = i.browser.applyDefaultHeaders(page); err != nil {
return nil, nil, err
}

Comment on lines +64 to +67
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Good placement; ensure Accept-Language still applies with no custom headers.

Calling applyDefaultHeaders right after setting Timeout is correct. With the current engine implementation, Accept-Language won’t be set if defaultHeaders is empty (regression). Please merge the engine.go fix to always apply Accept-Language unless the user provided one.

To confirm coverage and avoid missed call sites:


🏁 Script executed:

#!/bin/bash
# Find all Page creations and check that default headers are applied.
rg -n 'Page\s*\(\s*proto\.TargetCreateTarget' -A2
rg -n 'SetExtraHeaders\s*\(' -A2

Length of output: 487


All page creation sites covered; merge Accept-Language fix

The placement of applyDefaultHeaders immediately after setting Timeout in page.go is correct and covers all page creation calls. However, until the engine patch is merged, Accept-Language won’t be applied when defaultHeaders is empty.

Key locations checked:

  • Page creation in pkg/protocols/headless/engine/page.go:58
  • SetExtraHeaders call in pkg/protocols/headless/engine/engine.go:157–159

Action required:

  • Merge the fix in engine.go to ensure Accept-Language is always set unless explicitly overridden by the user.
🤖 Prompt for AI Agents
In pkg/protocols/headless/engine/page.go around lines 64 to 67,
applyDefaultHeaders is correctly placed but currently Accept-Language is not
applied when defaultHeaders is empty; merge the fix from
pkg/protocols/headless/engine/engine.go (around lines 157–159) into the codebase
so that SetExtraHeaders ensures Accept-Language is always added unless the user
explicitly sets it—update SetExtraHeaders logic to insert Accept-Language into
headers when missing (or when defaultHeaders is empty) before it’s passed to
applyDefaultHeaders and ensure the merged change is used by page creation paths.

if i.browser.customAgent != "" {
if userAgentErr := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); userAgentErr != nil {
return nil, nil, userAgentErr
Expand Down Expand Up @@ -130,10 +134,6 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map
return nil, nil, err
}

if _, err := page.SetExtraHeaders([]string{"Accept-Language", "en, en-GB, en-us;"}); err != nil {
return nil, nil, err
}

// inject cookies
// each http request is performed via the native go http client
// we first inject the shared cookies
Expand Down
Loading