nuclei icon indicating copy to clipboard operation
nuclei copied to clipboard

[BUG] Template context confusion when using the flow protocol while mass-scanning

Open nisay759 opened this issue 6 months ago • 2 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues.

Current Behavior

I've written a simple nuclei template that (for the sake of this example) looks for Readme files in a WordPress' website plugins/themes locations. The steps are the following:

  1. Issue an http request to the wesite's webroot and extract script/style/img imports using xpath
  2. Clean the imports to only include the URL up to the plugin's or theme's root
  3. For each theme/plugin root, issue an http request to look for the files README.md or README.txt

The template is as follows:

id: wordpress_readme

info:
  name: WordPress readme detection
  author: nisay759
  severity: info
  tags: readme,wordpress,themes,plugins

flow: |
  // get imports from website's root
  http(1);

  let uniq = Dedupe();

  // get unique webroot of each import
  for (let path of iterate(template["imports"])) {
    let pathArray = path.split("/");
    let rootIdx = pathArray.indexOf("wp-content") + 3;
    let finalUrl = pathArray.slice(0, rootIdx).join("/");
    uniq.Add(finalUrl);
  }

  // for each import, look for readme
  for (let url of iterate(uniq.Values())) {
    set("target", url);
    http(2);
  }

http:
  # http(1) - Query web root and extract themes/plugins imports
  - method: GET
    redirects: true
    path:
      - "{{BaseURL}}"

    extractors:
      - type: xpath
        name: "imports"
        internal: true
        xpath:
          - "/html/*/script/@src[contains(.,'wp-content/plugins/')]"
          - "/html/*/script/@src[contains(.,'wp-content/themes/')]"
          - "/html/*/style/@src[contains(.,'wp-content/themes/')]"
          - "/html/*/img/@src[contains(.,'wp-content/themes/')]"

  # http(2) - Given a theme/plugin "target", look for Readme file
  - method: GET
    path:
      - "{{target}}/README.md"
      - "{{target}}/README.txt"

    stop-at-first-match: true
    matchers:
      - type: status
        status:
          - 200

The template runs as expected when running against a single host. I ran it against https://wordcamp.org/ since they have a public bug bounty program:

../nuclei -proxy http://127.0.0.1:8080 -t wordpress_readme.yaml -u https://wordcamp.org        
                                                                                                                          
                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.4

		projectdiscovery.io

[INF] Current nuclei version: v3.4.4 (unknown) - remove '-duc' flag to enable update checks
[INF] Current nuclei-templates version: v9.8.9 (unknown) - remove '-duc' flag to enable update checks
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 0
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[wordpress_readme] [http] [info] https://central.wordcamp.org/wp-content/plugins/gutenberg/README.md
[INF] Scan completed in 3.601335048s. 1 matches found.

But when I run the template against a list of targets that contains the same previous host, I get no results. The list size seems to matter, and for a few hosts the template works just fine. Over 30 hosts, the results start becoming inconsistent.

For example, let's consider the following list that's comprised of Alexa's Top 29 hosts + our previous host, making it 30 targets:

https://google.com
https://youtube.com
https://facebook.com
https://baidu.com
https://wikipedia.org
https://qq.com
https://taobao.com
https://yahoo.com
https://tmall.com
https://amazon.com
https://twitter.com
https://sohu.com
https://live.com
https://jd.com
https://vk.com
https://instagram.com
https://sina.com.cn
https://weibo.com
https://reddit.com
https://login.tmall.com
https://360.cn
https://yandex.ru
https://linkedin.com
https://blogspot.com
https://netflix.com
https://twitch.tv
https://whatsapp.com
https://yahoo.co.jp
https://csdn.net
https://wordcamp.org

Running nuclei against this list yields no results :

../nuclei -proxy http://127.0.0.1:8080 -t wordpress_readme.yaml -l list.txt                         

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.4

		projectdiscovery.io

[INF] Current nuclei version: v3.4.4 (unknown) - remove '-duc' flag to enable update checks
[INF] Current nuclei-templates version: v9.8.9 (unknown) - remove '-duc' flag to enable update checks
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 0
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 30
[INF] Scan completed in 2.540299977s. No results found.

The position of the target in the list file doesn't seem to change the outcome.

I have noticed one curious behaviour though: Since https://wordcamp.org redirects to https://central.wordcamp.org, using the latter URL yields the expected result (maybe some internal alphabetical sorting of hosts ?).

I've digged through the documentation, and found the following mention in https://docs.projectdiscovery.io/tools/nuclei/mass-scanning-cli:

(Note: Nuclei by default reuses javascript runtimes to avoid overhead of creating new runtimes for each request)

Which made me think that maybe the uniq variable gets overwritten with an empty Dedupe instance when other hosts are scanned, since they all share the same runtime. With this assumption in mind, I edited the template as following:

id: wordpress_readme

info:
  name: WordPress readme detection
  author: nisay759
  severity: info
  tags: readme,wordpress,themes,plugins

flow: |
  // get imports from website's root
  http(1);

  template["{{BaseURL}}_results"] = Dedupe();

  // get unique webroot of each import
  for (let path of iterate(template["imports"])) {
    let pathArray = path.split("/");
    let rootIdx = pathArray.indexOf("wp-content") + 3;
    let finalUrl = pathArray.slice(0, rootIdx).join("/");
    template["{{BaseURL}}_results"].Add(finalUrl);
  }

  // for each import, look for readme
  for (let url of iterate(template["{{BaseURL}}_results"].Values())) {
    set("target", url);
    http(2);
  }

http:
  # http(1) - Query web root and extract themes/plugins imports
  - method: GET
    redirects: true
    path:
      - "{{BaseURL}}"

    extractors:
      - type: xpath
        name: "imports"
        internal: true
        xpath:
          - "/html/*/script/@src[contains(.,'wp-content/plugins/')]"
          - "/html/*/script/@src[contains(.,'wp-content/themes/')]"
          - "/html/*/style/@src[contains(.,'wp-content/themes/')]"
          - "/html/*/img/@src[contains(.,'wp-content/themes/')]"

  # http(2) - Given a theme/plugin "target", look for Readme file
  - method: GET
    path:
      - "{{target}}/README.md"
      - "{{target}}/README.txt"

    stop-at-first-match: true
    matchers:
      - type: status
        status:
          - 200

In this updated version of the template, let uniq = Dedupe() becomes template["{{BaseURL}}_results"] = Dedupe(), so that each host's results are stored in a unique key of the template map.

With this change, the template seems to work as expected:

../nuclei -proxy http://127.0.0.1:8080 -t wordpress_readme_2.yaml -l list.txt                       

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.4

		projectdiscovery.io

[INF] Current nuclei version: v3.4.4 (unknown) - remove '-duc' flag to enable update checks
[INF] Current nuclei-templates version: v9.8.9 (unknown) - remove '-duc' flag to enable update checks
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 0
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 30
[wordpress_readme] [http] [info] https://central.wordcamp.org/wp-content/plugins/gutenberg/README.md
[INF] Scan completed in 13.148207118s. 1 matches found.

Notes:

  • In the examples above, I'm running the template through a proxy (to inspect the requests that are issued by nuclei). The behavior is the same regardless of the type of proxy used, or whether a proxy is used at all. I omitted those cases for the sake of brevity.
  • The issue arises when scanning in template-spray mode. The host-spray mode yields the expected results, but it's kind of counterproductive using this mode when running a single template.

Expected Behavior

Variables defined whithin a flow block should be scoped to the current host being scanned.

If a fix is not possible, the documentation should be updated to mention this kind of edge-case.

Steps To Reproduce

Steps to reproduce are described in the previous sections.

Relevant log output


Environment

- OS: Arch Linux
- Nuclei: v3.4.4 (from GitHub releases)
- Nuclei's `config.yaml` content:


scan-strategy: "template-spray"
exclude-tags: []
disable-update-check: true
disable-unsigned-templates: false
header:
  - User-Agent: "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"

Anything else?

No response

nisay759 avatar Jun 13 '25 11:06 nisay759

Very well-written issue. Thanks for providing that info! We'll look into it and investigate further.

dwisiswant0 avatar Jun 16 '25 13:06 dwisiswant0

@dwisiswant0 the acutal error that might lead to root cause, this get displayed as warning while running with -v option.

 <- SyntaxError: Identifier 'uniq' has already been declared at <eval>:1:1(0)

ehsandeep avatar Jun 16 '25 14:06 ehsandeep

@nisay759 this is being fixed in https://github.com/projectdiscovery/nuclei/pull/6282

ehsandeep avatar Jun 27 '25 14:06 ehsandeep

@ehsandeep Thanks for the heads up.

I tried to test with the fix that was just merged into the dev branch, but I still have the same issue when running the template through a socks proxy. The problem seems to be fixed when running nuclei without a proxy, or when proxying through an http proxy (which in turn proxies to the same socks proxy).

Here's my build process. If I missed a step or did something wrong please let me know

  1. Get the latest changes from the git repo and make sure I have the fix in the local dev branch
➜  nuclei git:(dev) git pull
Already up to date.

➜  nuclei git:(dev) git log HEAD^..HEAD
commit 2b729e40373cc81c13ee104844b3839bbe96c559 (HEAD -> dev, origin/dev, origin/HEAD)
Author: Tarun Koyalwar <[email protected]>
Date:   Mon Jun 30 15:13:00 2025 +0530

    fix context leak in flow (#6282)
    
    * fix context leak in flow
    
    * handle sizedwaitpool when not reused
  1. Build nuclei using Dockerfile
docker buildx build . -t nuclei:test
  1. Start a container with the new image
docker run --rm -it --entrypoint /bin/sh -v $PWD/list.txt:/root/list.txt -v $PWD/wordpress_readme.yaml:/root/wordpress_readme.yaml nuclei:test
/ # cd /root/
~ # ls
list.txt               wordpress_readme.yaml

Running the template directly shows no problem, as expected:

~ # nuclei -t wordpress_readme.yaml -l list.txt -v

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.5

		projectdiscovery.io

[VER] Started metrics server at localhost:9092
[INF] Current nuclei version: v3.4.5 (latest)
[INF] Current nuclei-templates version: v10.2.3 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 105
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 30
[VER] [wordpress_readme] Sent HTTP request to https://twitch.tv
[VER] [wordpress_readme] Sent HTTP request to https://wikipedia.org
[VER] [wordpress_readme] Sent HTTP request to https://google.com
[VER] [wordpress_readme] Sent HTTP request to https://reddit.com
[VER] [wordpress_readme] Sent HTTP request to https://whatsapp.com
[VER] [wordpress_readme] Sent HTTP request to https://live.com
[VER] [wordpress_readme] Sent HTTP request to https://twitter.com
[VER] [wordpress_readme] Sent HTTP request to https://blogspot.com
[VER] [wordpress_readme] Sent HTTP request to https://instagram.com
[VER] [wordpress_readme] Sent HTTP request to https://vk.com
[VER] [wordpress_readme] Sent HTTP request to https://facebook.com
[VER] [wordpress_readme] Sent HTTP request to https://amazon.com
[VER] [wordpress_readme] Sent HTTP request to https://youtube.com
[VER] [wordpress_readme] Sent HTTP request to https://linkedin.com
[VER] [wordpress_readme] Sent HTTP request to https://wordcamp.org
[VER] [wordpress_readme] Sent HTTP request to https://login.tmall.com
[VER] [wordpress_readme] Sent HTTP request to https://netflix.com
[VER] [wordpress_readme] Sent HTTP request to https://yahoo.com
[VER] [wordpress_readme] Sent HTTP request to https://yandex.ru
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/gutenberg/README.md
[wordpress_readme] [http] [info] https://central.wordcamp.org/wp-content/plugins/gutenberg/README.md
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/tagregator/README.md
[VER] [wordpress_readme] Sent HTTP request to https://qq.com
[VER] [wordpress_readme] Sent HTTP request to https://baidu.com
[VER] [wordpress_readme] Sent HTTP request to https://jd.com
[VER] [wordpress_readme] Sent HTTP request to https://sohu.com
[VER] [wordpress_readme] Sent HTTP request to https://360.cn
[VER] [wordpress_readme] Sent HTTP request to https://taobao.com
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/tagregator/README.txt
[VER] [wordpress_readme] Sent HTTP request to https://yahoo.co.jp
[VER] [wordpress_readme] Sent HTTP request to https://tmall.com
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/jetpack/README.md
[VER] [wordpress_readme] Sent HTTP request to https://weibo.com
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/jetpack/README.txt
[VER] [wordpress_readme] Sent HTTP request to https://sina.com.cn
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/themes/wordcamp-central-2012/README.md
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/themes/wordcamp-central-2012/README.txt
[VER] [wordpress_readme] Sent HTTP request to https://csdn.net
[INF] Scan completed in 13.841904568s. 1 matches found.

Running the template through an http proxy seems to work fine too :

~ # nuclei -proxy http://172.17.0.1:18080 -t wordpress_readme.yaml -l list.txt -v

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.5

		projectdiscovery.io

[VER] Using http://172.17.0.1:18080 as proxy server
[VER] Started metrics server at localhost:9092
[INF] Current nuclei version: v3.4.5 (latest)
[INF] Current nuclei-templates version: v10.2.3 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 105
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 30
[VER] [wordpress_readme] Sent HTTP request to https://reddit.com
[VER] [wordpress_readme] Sent HTTP request to https://twitch.tv
[VER] [wordpress_readme] Sent HTTP request to https://wikipedia.org
[VER] [wordpress_readme] Sent HTTP request to https://whatsapp.com
[VER] [wordpress_readme] Sent HTTP request to https://google.com
[VER] [wordpress_readme] Sent HTTP request to https://vk.com
[VER] [wordpress_readme] Sent HTTP request to https://twitter.com
[VER] [wordpress_readme] Sent HTTP request to https://linkedin.com
[VER] [wordpress_readme] Sent HTTP request to https://facebook.com
[VER] [wordpress_readme] Sent HTTP request to https://instagram.com
[VER] [wordpress_readme] Sent HTTP request to https://blogspot.com
[VER] [wordpress_readme] Sent HTTP request to https://jd.com
[VER] [wordpress_readme] Sent HTTP request to https://live.com
[VER] [wordpress_readme] Sent HTTP request to https://sohu.com
[VER] [wordpress_readme] Sent HTTP request to https://sina.com.cn
[VER] [wordpress_readme] Sent HTTP request to https://tmall.com
[VER] [wordpress_readme] Sent HTTP request to https://youtube.com
[VER] [wordpress_readme] Sent HTTP request to https://taobao.com
[VER] [wordpress_readme] Sent HTTP request to https://wordcamp.org
[VER] [wordpress_readme] Sent HTTP request to https://amazon.com
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/gutenberg/README.md
[VER] [wordpress_readme] Sent HTTP request to https://yandex.ru
[wordpress_readme] [http] [info] https://central.wordcamp.org/wp-content/plugins/gutenberg/README.md
[VER] [wordpress_readme] Sent HTTP request to https://yahoo.com
[VER] [wordpress_readme] Sent HTTP request to https://netflix.com
[VER] [wordpress_readme] Sent HTTP request to https://360.cn
[VER] [wordpress_readme] Sent HTTP request to https://login.tmall.com
[VER] [wordpress_readme] Sent HTTP request to https://weibo.com
[VER] [wordpress_readme] Sent HTTP request to https://baidu.com
[VER] [wordpress_readme] Sent HTTP request to https://qq.com
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/themes/wordcamp-central-2012/README.md
[VER] [wordpress_readme] Sent HTTP request to https://yahoo.co.jp
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/themes/wordcamp-central-2012/README.txt
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/tagregator/README.md
[VER] [wordpress_readme] Sent HTTP request to https://csdn.net
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/tagregator/README.txt
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/jetpack/README.md
[VER] [wordpress_readme] Sent HTTP request to https://central.wordcamp.org/wp-content/plugins/jetpack/README.txt
[INF] Scan completed in 4.900174417s. 1 matches found.

Runing the template through a socks5 proxy yields the same error :

~ # nuclei -proxy socks5://172.17.0.1:9090 -t wordpress_readme.yaml -l list.txt -v

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.5

		projectdiscovery.io

[VER] Using socks5://172.17.0.1:9090 as socket proxy server
[VER] Started metrics server at localhost:9092
[INF] Current nuclei version: v3.4.5 (latest)
[INF] Current nuclei-templates version: v10.2.3 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 105
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 30
[VER] [wordpress_readme] Sent HTTP request to https://reddit.com
[VER] [wordpress_readme] Sent HTTP request to https://twitch.tv
[VER] [wordpress_readme] Sent HTTP request to https://wikipedia.org
[VER] [wordpress_readme] Sent HTTP request to https://whatsapp.com
[VER] [wordpress_readme] Sent HTTP request to https://twitter.com
[VER] [wordpress_readme] Sent HTTP request to https://google.com
[VER] [wordpress_readme] Sent HTTP request to https://instagram.com
[VER] [wordpress_readme] Sent HTTP request to https://facebook.com
[VER] [wordpress_readme] Sent HTTP request to https://vk.com
[VER] [wordpress_readme] Sent HTTP request to https://youtube.com
[VER] [wordpress_readme] Sent HTTP request to https://taobao.com
[VER] [wordpress_readme] Sent HTTP request to https://blogspot.com
[VER] [wordpress_readme] Sent HTTP request to https://amazon.com
[VER] [wordpress_readme] Sent HTTP request to https://tmall.com
[VER] [wordpress_readme] Sent HTTP request to https://linkedin.com
[VER] [wordpress_readme] Sent HTTP request to https://sohu.com
[VER] [wordpress_readme] Sent HTTP request to https://wordcamp.org
[VER] [wordpress_readme] Sent HTTP request to https://netflix.com
[VER] [wordpress_readme] Sent HTTP request to https://live.com
[VER] [wordpress_readme] Sent HTTP request to https://yahoo.com
[VER] [wordpress_readme] Sent HTTP request to https://sina.com.cn
[VER] [wordpress_readme] Sent HTTP request to https://yandex.ru
[VER] [wordpress_readme] Sent HTTP request to https://login.tmall.com
[VER] [wordpress_readme] Sent HTTP request to https://jd.com
[VER] [wordpress_readme] Sent HTTP request to https://weibo.com
[VER] [wordpress_readme] Sent HTTP request to https://360.cn
[VER] [wordpress_readme] Sent HTTP request to https://yahoo.co.jp
[VER] [wordpress_readme] Sent HTTP request to https://qq.com
[VER] [wordpress_readme] Sent HTTP request to https://baidu.com
[WRN] [wordpress_readme] Could not execute step on https://csdn.net: [:RUNTIME] failed to execute flow
// get imports from website's root
http(1);

let uniq = Dedupe();

// get unique webroot of each import
for (let path of iterate(template["imports"])) {
  let pathArray = path.split("/");
  let rootIdx = pathArray.indexOf("wp-content") + 3;
  let finalUrl = pathArray.slice(0, rootIdx).join("/");
  uniq.Add(finalUrl);
}

// for each import, look for readme
for (let url of iterate(uniq.Values())) {
  set("target", url);
  http(2);
}

 <- TypeError: Cannot read property 'imports' of undefined at <eval>:7:34(11)
[INF] Scan completed in 30.036850959s. No results found.

The socks proxy doesn't seem to be the issue, as confirmed with curl :

~ # apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/4) Installing c-ares (1.33.1-r0)
(2/4) Installing libpsl (0.21.5-r1)
(3/4) Installing libcurl (8.12.1-r0)
(4/4) Installing curl (8.12.1-r0)
Executing busybox-1.36.1-r28.trigger
OK: 631 MiB in 200 packages

~ # curl -x socks5://172.17.0.1:9090 ipinfo.io/ip
<redacted_ip_of_the_socks_server>

nisay759 avatar Jun 30 '25 10:06 nisay759

Update: It's not the same issue, I think this is something different.

I redid the tests with the previous nuclei release (3.4.5), and the old error was :

<- SyntaxError: Identifier 'uniq' has already been declared at <eval>:1:1(0)

This new error (<- TypeError: Cannot read property 'imports' of undefined at <eval>:7:34(11)) is also present in 3.4.5 when running the template through a socks proxy.

@ehsandeep Do you think this is related to this issue, or should I open a separate one ?

nisay759 avatar Jun 30 '25 10:06 nisay759

@nisay759 This error <- TypeError: Cannot read property 'imports' of undefined at <eval>:7:34(11) is likely expected when imports doesn’t hold any value, typically in cases where the site isn’t running WordPress. The error is verbose but should be harmless. Do you have any example hosts where imports has values from response but still triggers this error?

ehsandeep avatar Jun 30 '25 11:06 ehsandeep

This error <- TypeError: Cannot read property 'imports' of undefined at <eval>:7:34(11) is likely expected when imports doesn’t hold any value, typically in cases where the site isn’t running WordPress.

In that case, running the template directly or through an http proxy should yield the exact same behavior as when using a socks proxy, which is not the case here.

Also, the error suggests that the variable template is indefined, and the error is thrown when trying to read the property imports in line 16 :

  for (let path of iterate(template["imports"])) {
    // [...]

The error is not harmless: The 3rd example (with socks proxy) shows that no results were found (nuclei exits as soon as the error is encountered), whereas 1 result for the target https://wordcamp.org is expected, as shown in examples 1 and 2.

Do you have any example hosts where imports has values from response but still triggers this error?

I couldn't reproduce the bug with a list of targets containing only wordpress instances. However, I found that the culprit is https://csdn.net :

./nuclei -proxy socks5://172.17.0.1:9090 -t wordpress_readme.yaml -u https://csdn.net -v                                                 

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.5

		projectdiscovery.io

[VER] Using socks5://172.17.0.1:9090 as socket proxy server
[VER] Started metrics server at localhost:9092
[INF] Current nuclei version: v3.4.5 (unknown) - remove '-duc' flag to enable update checks
[INF] Current nuclei-templates version: v9.8.9 (unknown) - remove '-duc' flag to enable update checks
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 0
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[WRN] [wordpress_readme] Could not execute step on https://csdn.net: [:RUNTIME] failed to execute flow
// get imports from website's root
http(1);

let uniq = Dedupe();

// get unique webroot of each import
for (let path of iterate(template["imports"])) {
  let pathArray = path.split("/");
  let rootIdx = pathArray.indexOf("wp-content") + 3;
  let finalUrl = pathArray.slice(0, rootIdx).join("/");
  uniq.Add(finalUrl);
}

// for each import, look for readme
for (let url of iterate(uniq.Values())) {
  set("target", url);
  http(2);
}

 <- TypeError: Cannot read property 'imports' of undefined at <eval>:7:34(11)
[INF] Scan completed in 5.440468404s. No results found.

I'm still not sure what does this host have in particular that triggers this error, which is intriguing because it only shows when using a socks proxy.

For information, I managed to trigger the same error when specifying targets with closed ports, and the error is returned regardless of the proxy :

✗ ./nuclei -t wordpress_readme.yaml -u http://localhost:12345 -v            

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.4.5

		projectdiscovery.io

[VER] Started metrics server at localhost:9092
[INF] Current nuclei version: v3.4.5 (unknown) - remove '-duc' flag to enable update checks
[INF] Current nuclei-templates version: v9.8.9 (unknown) - remove '-duc' flag to enable update checks
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 0
[INF] Templates loaded for current scan: 1
[WRN] Loading 1 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[WRN] [wordpress_readme] Could not execute step on http://localhost:12345: [:RUNTIME] failed to execute flow
// get imports from website's root
http(1);

let uniq = Dedupe();

// get unique webroot of each import
for (let path of iterate(template["imports"])) {
  let pathArray = path.split("/");
  let rootIdx = pathArray.indexOf("wp-content") + 3;
  let finalUrl = pathArray.slice(0, rootIdx).join("/");
  uniq.Add(finalUrl);
}

// for each import, look for readme
for (let url of iterate(uniq.Values())) {
  set("target", url);
  http(2);
}

 <- TypeError: Cannot read property 'imports' of undefined at <eval>:7:34(11)
[INF] Scan completed in 1.395961ms. No results found.

I'm still unable to pinpoint the root cause. I'll do some more digging instead of polluting this thread, and I'll open another issue when I have more details.

Thanks for the assistance @ehsandeep !

nisay759 avatar Jun 30 '25 13:06 nisay759