Dwi Siswanto

Security R&D | Rapper | Shitposter | ACAB How to Scan Continuously with Nuclei? | Dwi Siswanto

How to Scan Continuously with Nuclei?

September 12, 2020

I know y’all r lazy.


Before going to steps, have you read how to Weaponizes nuclei Workflows to Pwn All the Things?

Nuclei templates are curated list of template files for the nuclei engine provided by Project Discovery team as well as contributed by the community, which means, this repository will always undergo changes (whether it’s fixing for false-positives or adding new templates).


The nuclei program already has flags for updating templates, with the “-update-directory” or “-update-templates” flag. However, I have Nuclei templates as a Git repository because I also contribute there.


By the way, I have created a script to run nuclei with all templates automatically, please check nucleir.sh here. Usage is “nucleir [-target/-l] [domain.tld/urls.txt]”.

But, How with Continuously?

Let’s say you have a persistent target list, and you want to scan with the latest templates continuously, of course you must have the latest set of templates!

Before I thought about this method, I ran auto-pull with cron every hour on nuclei-templates, but without running the scan, as I didn’t catch what the previous changes were to templates.

I created two Bash files, one for defining functions, and one for performing scans.

parseArgs is a function to parse and validate required arguments, isUpdated to check if your nuclei-templates is up to date or nah, then getHead to show the commit logs line-by-line and read first line, then retrieve the commit ID. Most important one are getChanges function, from this function we can know; there are changes to any files by doing a commit comparison with Git diff tool.

Then, our main file are:

As an explanation, we will catch all arguments and pass them to parseArgs function to validate. If the validation is successful, it will change directory to nuclei-templates, then, is this local equivalent to remote branch (newest)? If so, the program will exit, otherwise; it will pull the remote repository. But, before pulling, we store the current commit ID to make comparisons with the last commit ID by calling getChanges function. Last step, we will run nuclei with the templates that have changed. The sed will append “-t” to each of the first lines, because if we do “git diff aaaa..bbbb”, the result will be:


After using sed will be:

-t files/file-A.yaml
-t files/file-B.yaml
-t cves/CVE-YYYY-NNNN.yaml
-t vulnerabilities/vuln.yaml

Finally, replace newline with a space using tr:

-t files/file-A.yaml -t files/file-B.yaml -t cves/CVE-YYYY-NNNN.yaml -t vulnerabilities/vuln.yaml

So, usage nuclei to be consumed as in the last line are:

nuclei [arg 1] [arg 2] -t files/file-A.yaml -t files/file-B.yaml -t cves/CVE-YYYY-NNNN.yaml -t vulnerabilities/vuln.yaml


Have a look at full version in my repository in continuous-nuclei.

* Sorry I didn’t use the nuclei output flag, because I’m using slackcat. LMAO.

Cron at minute 0.

To use with precision, run this every hour with cron. Apart from getting the latest nuclei-templates, it will also perform scans on the targets we provide every hour! e.g. —

0 * * * * /path/to/continuous-nuclei/run -l /path/to/urls.txt

Last but not least!

Please DO NOT scan a target that you are not positive you have permission to be testing! As a pentester, it is your responsibility to ensure that you have permission from the owner of a target before you start testing it. This is why target validation should always be your first step when beginning an engagement.