Skip to content

v3.8.0 (prep)#7344

Merged
ehsandeep merged 127 commits intomainfrom
dev
Apr 16, 2026
Merged

v3.8.0 (prep)#7344
ehsandeep merged 127 commits intomainfrom
dev

Conversation

@ehsandeep
Copy link
Copy Markdown
Member

Proposed changes

Proof

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

JawsKim and others added 30 commits January 8, 2026 17:36
Signed-off-by: Dwi Siswanto <git@dw1.io>
…ing functions

When a variable value contains unresolved {{...}} markers (e.g. {{contact_id}})
and is passed through an encoding function like base64(), the markers get encoded
into an opaque blob that ContainsUnresolvedVariables cannot detect, causing
requests to fire with garbage data instead of being blocked.

Before evaluating an expression, check if its variable values contain unresolved
markers. If so, propagate those markers into the output so the existing downstream
check catches them with the correct variable names.
Resume files are runtime artifacts and SHOULD NOT
be presented as persistent config.

Update reset messaging to separate config vs cache
and explicitly include resume state under cache
cleanup. Also delete the cache dir during `-reset`
to keep behavior aligned with the new semantics.

Close #6792

Signed-off-by: Dwi Siswanto <git@dw1.io>
Fix ambiguous interpretation of IPv6 addresses
like "::1:8065" by bracketing them before URL
formation to make sure they are treated as hosts
rather than "host:port" pairs.

Close #6960

Signed-off-by: Dwi Siswanto <git@dw1.io>
Prev. project keyed cache lookups from dumped HTTP
request bytes alone. For eq requests, this allowed
"http" and "https" targets to collide and reuse
cached responses across schemes.

Derive a scoped cache key by prefixing normalized
scheme://host before `projectfile.{Get,Set}`
keying input in the HTTP protocol path.

Close #6866

Signed-off-by: Dwi Siswanto <git@dw1.io>
Apply request annotations during `unsafe` raw
request generation so @Host/@timeout/etc affect
the effective target and execution context.

Strip leading annotation directives from `unsafe`
wire bytes before sending, since `rawhttp`
transmits raw payload verbatim and annotation
lines can produce malformed HTTP requests.

Close #6747

Signed-off-by: Dwi Siswanto <git@dw1.io>
* Updated `.github/workflows/tests.yaml`:
  * Added `GITHUB_TOKEN` to `validate` job to
    support `make template-validate`.
* Updated `.github/workflows/flamegraph.yaml`:
  * Added `GITHUB_TOKEN` to `flamegraph` job for
    `nuclei -update-templates`.
* Updated `.github/workflows/generate-pgo.yaml`:
  * Added `GITHUB_TOKEN` to `pgo` job for
    `nuclei -update-templates`.

This make sure auth'd GitHub API calls during
template updates, avoiding rate limit issues.

Signed-off-by: Dwi Siswanto <git@dw1.io>
The time_delay analyzer's reqSender rebuilt follow-up requests from
gr.Component.Rebuild() which clones the component's base request.  That
base request is parsed from rule.BaseRequest *before* post-parse header
injection happens (custom -H flags, auth provider headers, cookies).
As a result every follow-up request was sent without the headers that the
original triggering request carried, including Cookie/Authorization —
the server rejected them or ran the SQL in an unauthenticated context.

Fix: after Rebuild(), copy the complete header set from gr.Request (the
original fuzz-generated request, which has all headers) into the rebuilt
request.  This mirrors the same approach used everywhere else in the
request pipeline and makes the time_delay analyzer behave consistently.

Fixes #7106
…onsive

In host-spray mode (executeTemplatesOnTarget), the goroutine-spawn loop
iterated over ALL templates for a target even after HostErrorsCache had
marked that target as permanently unresponsive.  Each spawned goroutine
immediately detected the unresponsive state and wrote a 'skipped' event
to the output before returning.

Without JSON output the skip events are cheap (no I/O), so the scan
still finishes quickly.  With -j or -je enabled, each skip event
triggers a synchronous JSON write; for a full template set (~18k
templates) this serialises thousands of writes and keeps the process
running for hours instead of the expected few minutes (issue #7049).

Fix: check HostErrorsCache at the top of the template-spawn loop and
break out as soon as the target is known to be permanently unresponsive.
This mirrors the identical guard already present in the template-spray
path (executeTemplateWithTargets, line 153) and avoids spawning
O(templates) no-op goroutines for dead hosts.

Fixes #7049
Tag listing (`-tgl`) output was moved to debug log
level, making it invisible during normal runs.
Restore tag output to default log level (Print)
for better usability.

Fixes #7142

Signed-off-by: Dwi Siswanto <git@dw1.io>
Uses metadata caching via catalog index to reduce
runtime overhead.

Add `(*Store).LoadTemplateTags` for efficient tag
aggregation.

Signed-off-by: Dwi Siswanto <git@dw1.io>
…/use-Print-instead-to-listAvailableStoreTags

fix(runner): use Print instead to listAvailableStoreTags
…respect-raw-annotations-in-unsafe-mode

feat(http): respect `annotations` in `unsafe` mode
…ypes/make-resume-state-as-cache-data

refactor(types)!: make resume state as cache data
…responsive-early

fix(core): stop spawning template goroutines in host-spray once host is unresponsive
docs: update outdated documentation links in all translations
…improvement

fix: add Snapshot method to prevent InFlight map race condition
dwisiswant0 and others added 7 commits April 8, 2026 05:43
Signed-off-by: Dwi Siswanto <git@dw1.io>
…am (#7335)

Updates `github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream` from 1.6.11 to 1.7.8
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](aws/aws-sdk-go-v2@service/rum/v1.6.11...service/m2/v1.7.8)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream
  dependency-version: 1.7.8
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* fix(js): respect `allow-local-file-access` in `require`

The goja `require() `function used the default
host filesystem loader which let JavaScript
templates import any local files even when
`allow-local-file-access` was disabled.

Pooled runtimes kept `require()` state around so
a module loaded during a privileged execution
could remain cached for a later restricted one.

Rebuild the require registry per execution after
setting the execution context, and route file-
backed module loads to preserve native modules
while enforcing the same sandbox rules (as
`nuclei/fs`).

Signed-off-by: Dwi Siswanto <git@dw1.io>

* fix: cross-platform sandbox path checks

Replace lexical prefix checks in the template file
sandbox with a shared path containment helper that
canonicalizes both paths before comparing them to
prevent false rejections when the configured
templates directory and the resolved file path
differ only due to symlink expansion on macOS or
path normalization on Windows.

Apply the helper in `protocolstate.NormalizePath()`
and `Options.GetValidAbsPath()` so JS `require()`-
based module loads and helper file resolution use
the same rules.

Signed-off-by: Dwi Siswanto <git@dw1.io>

---------

Signed-off-by: Dwi Siswanto <git@dw1.io>
* fix(expressions): avoid helper eval in literal checks

`hasLiteralsOnly()` currently evaluates helper
expressions while deciding whether "{{...}}"
contains unresolved variables, which makes
validation paths run side-effectful helpers.

Just replace that runtime eval with a
`Vars()` len check so unresolved-variable
detection literally stays literal (am I writing it
right?), and of course side-effect free.

Also make `Evaluate()` return template-authored
expression compile/eval errors instead of
logging and then keep continuing, so malformed
helper calls still fail in the rendering path.

Fixes #7320

Signed-off-by: Dwi Siswanto <git@dw1.io>

* fix(javascript): avoid nil map panic on arg eval failure

`getArgsCopy()` logs and counts argument
evaluation failures, but continues to store Port
in `argsCopy` even when `evaluateArgs()` returns.
This causes malformed JavaScript args like
"{{base64()}}" to panic instead of returning the
original error.

Return the evaluation error immediately after
reporting it to prevent the panic and make sure
proper error propagation.

Signed-off-by: Dwi Siswanto <git@dw1.io>

---------

Signed-off-by: Dwi Siswanto <git@dw1.io>
Bumps the modules group with 2 updates: [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) and [github.com/projectdiscovery/cdncheck](https://github.com/projectdiscovery/cdncheck).


Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.75 to 0.2.76
- [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases)
- [Commits](projectdiscovery/wappalyzergo@v0.2.75...v0.2.76)

Updates `github.com/projectdiscovery/cdncheck` from 1.2.30 to 1.2.31
- [Release notes](https://github.com/projectdiscovery/cdncheck/releases)
- [Commits](projectdiscovery/cdncheck@v1.2.30...v1.2.31)

---
updated-dependencies:
- dependency-name: github.com/projectdiscovery/wappalyzergo
  dependency-version: 0.2.76
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: modules
- dependency-name: github.com/projectdiscovery/cdncheck
  dependency-version: 1.2.31
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
when creating default limiter.

The engine could be set up with custom rate limits
through `WithOptions()`, but internal was still
hardcoding `e.rateLimiter` to 150 RPS when no
global limiter was explicitly set.

Now it builds the default limiter from the
resolved options:
1. Applies `RateLimitMinute` translation,
2. Defaults `RateLimitDuration` to 1s when
   `RateLimit > 0` and no duration is given, then
3. Creates the limiter via `GetRateLimiter()`.

Fixes #7341

Signed-off-by: Dwi Siswanto <git@dw1.io>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2d4bb847-5a1e-466e-8b63-fe3ab5326db8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'RunEnumeration Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: f893b6c Previous: 6f2ade6 Ratio
BenchmarkRunEnumeration/Multiproto - allocs/op 443719 allocs/op 196951 allocs/op 2.25

This comment was automatically generated by workflow using github-action-benchmark.

@dwisiswant0
Copy link
Copy Markdown
Member

@dwisiswant0
Copy link
Copy Markdown
Member

@github-actions comment was irrelevant.

Ref:

This basically confirms my assumption, but then after the (native tests) commit, benchstat shows the exact opposite (data is literally contradicting the alert), yet somehow we're still seeing a marginal benefit (nets a ~1% reduction).

goos: linux
goarch: amd64
pkg: github.com/projectdiscovery/nuclei/v3/cmd/nuclei
cpu: AMD EPYC 9V74 80-Core Processor                
                            │  0e67be77   │             f893b6c0              │
                            │   sec/op    │   sec/op     vs base              │
RunEnumeration/Default-4       196.2 ± 1%    196.2 ± 1%       ~ (p=0.699 n=6)
RunEnumeration/Multiproto-4   368.9m ± 0%   361.4m ± 6%  -2.03% (p=0.004 n=6)
geomean                        8.508         8.421       -1.02%
                            │   0e67be77   │              f893b6c0              │
                            │     B/op     │     B/op      vs base              │
RunEnumeration/Default-4      4.248Gi ± 1%   4.247Gi ± 1%       ~ (p=0.699 n=6)
RunEnumeration/Multiproto-4   56.10Mi ± 0%   56.10Mi ± 0%       ~ (p=0.310 n=6)
geomean                       494.0Mi        494.0Mi       -0.01%
                            │  0e67be77   │             f893b6c0              │
                            │  allocs/op  │  allocs/op   vs base              │
RunEnumeration/Default-4      53.41M ± 1%   53.41M ± 1%       ~ (p=0.699 n=6)
RunEnumeration/Multiproto-4   393.7k ± 0%   393.7k ± 0%       ~ (p=0.310 n=6)
geomean                       4.586M        4.586M       -0.00%

Note

0e67be7: fix DAST skipping URLs with part: request and mode: multiple (#7326)
f893b6c: refactor: native tests (#7307)

See https://github.com/dwisiswant0/nuclei/actions/runs/24432728903/job/71380412282

The benchmark action is probably hitting some stale cache that's completely irrelevant now.

dwisiswant0 and others added 12 commits April 15, 2026 11:10
Signed-off-by: Dwi Siswanto <git@dw1.io>
…eader

Fix headless JS loading with -tlsi and addheader/setheader
Support service names in network template port field
…spect-WithOptions-rate-limit

fix(sdk): respect `WithOptions` rate limit
fix(installer): prevent unnecessary update checks
* Interrupt goja runtime on context cancel

* undo import formats

* do both actions in same go-routine to prevent any possible race condition

* Convert the watchdog, into a simpeler construction which still guarantees the same promises

* move the recover to the go routine, and return named return since we now can use the channel

* remove unnecessary tests

* add extra safety in case process refuses to get interrupted

* remove unnecessary ExecFuncWithTwoReturns

* remove named return values
@ehsandeep ehsandeep marked this pull request as ready for review April 16, 2026 16:51
@auto-assign auto-assign bot requested a review from dogancanbakir April 16, 2026 16:51
@neo-by-projectdiscovery-dev
Copy link
Copy Markdown

neo-by-projectdiscovery-dev bot commented Apr 16, 2026

Neo - PR Security Review

No security issues found

Comment @pdneo help for available commands. · Open in Neo

@ehsandeep ehsandeep removed the request for review from dogancanbakir April 16, 2026 19:34
@ehsandeep ehsandeep merged commit aa52d85 into main Apr 16, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.