~/tutorials/060-nuclei-templates-as-opinion.md
060: nuclei, templates as opinion
The scanner trilogy taught reading output. The fuzzer taught shaping questions. nuclei is both ideas fused into the modern shape of automated testing, and this lesson's title is its thesis: every template is an opinion, written by somebody, about what matters. Thirteen thousand opinions ship in the box. The skill is reading them as opinions, and the moment of power is writing your own.
What this lesson is for
nuclei runs YAML templates, each one a small program: send this, match that, report thus. The template library is community-maintained, enormous, updated weekly, and it encodes a worldview, what the community considers a finding worth a template, at what severity, checked how. Using nuclei well is not running all the templates. It is choosing subsets with intent, reading a template before you trust its verdict, and, when your context knows better than the library, writing the thirteen lines that carry your knowing.
What the reader meets
The lab box on the web lab page, and nuclei's own numbers first, because the scale is the first fact: the template list command counts thirteen thousand three hundred and twenty six templates. Thirteen thousand opinions about what a finding is, tagged by exposure, severity, technique, and running them all against one target is the noise floor of 057 raised to an art form. The professional default is subsets, by tag, by severity, by template age, chosen per engagement, and the choosing is a judgment you now have the parts for.
The stock run, exposure-tagged, medium and up, against the lab box:
$ nuclei -u http://172.31.20.2/ -tags exposure -severity medium,high,critical -silent
[configuration-listing] [http] [medium] http://172.31.20.2/config/
One row. A directory listing under config, found, labeled, severity-assigned by a template's author who has never seen this box. Every part of that row is the 054 discipline wearing YAML: the finding is said-so, the directory answers with an index, and the severity is an opinion from a stranger. Read with the trilogy's eyes, it is a good row. It is also, on this deliberately broken lab box, the tip of an iceberg, and the iceberg's underwater nine-tenths is the lesson.
Now the template as your opinion. The lab plants a config.bak.php in the web root, the same planted credential file from 057 and 058, and this time the finding is authored, from scratch, as a thirteen line YAML file:
id: backup-config-exposed
info:
name: Backup config file exposed
author: this lesson
severity: high
description: A config.bak.php answering 200 is an exposure by policy, regardless of content
http:
- method: GET
path:
- "{{BaseURL}}/config.bak.php"
matchers:
- type: status
status: [200]
Read it as prose, because it reads as prose: if a config.bak.php answers 200, that is high severity, by my policy, regardless of content. That is an opinion, complete, with an author and a severity and a reason. Fire it at the planted target:
[backup-config-exposed] [http] [high] http://172.31.20.2/config.bak.php
Found. And at a clean server with no such file, the same template answers nothing, scan completed, no results, exit clean. The opinion held its fire where it did not apply, which is what makes it an opinion rather than an alarm.
Sit with what just happened, because it is the lesson's center. The stock library, thirteen thousand templates, does not carry this check: config.bak.php is not a CVE, not a named tech, not a generic pattern the community templates on, because whether a backup file is an exposure depends on policy, and policy lives with the tester, not the library. Your thirteen lines found what thirteen thousand opinions could not see, because the opinion was yours to write. That is not nuclei being limited. That is the division of labor this whole tier has been walking toward: the tools carry the general, you carry the particular, and the template format is the bridge that lets your particular run at machine speed.
The instrument
The template anatomy, every part of which is a claim. The id and name are the finding's identity, what your report will call it. The severity is somebody's judgment, the template author's, and 054's kinds-of-yes applies: severity is not a fact about the target, it is an opinion about consequence, and the opinion is worth reading before the row reaches a client. The description is the why, and a good template's description is a one-line report paragraph. The http block is the question: this method, this path, these parameters. The matchers are the verdict: this status, this regex in the body, this word count. Question and verdict, written down, reviewable, diffable, which is everything a fuzzer run from 058 was not, and why nuclei templates are the honest unit of automated testing: the opinion is in the file, in the open, where anyone can read it and disagree.
Three habits make the tool yours. Read before you run: any template whose verdict will reach a report gets its file read first, nuclei -tl to list, the YAML is short, and thirty seconds of reading saves retracted findings. Subset with intent: tags and severity are the dials, and the engagement decides them, an exposure sweep on a first pass, cve-specific templates when a version claim from 059 needs a capability probe, tech templates against a stack you have already fingerprinted. And version your own: a private directory of your policy templates, kept like the baseline directory of 057, dated, because your opinions deserve the same memory your scans get.
Try it
- Run the stock exposure subset against your lab box, then read two of the templates that fired, the YAML files themselves, and write one sentence each: what does this template believe, and do I agree. You are practicing the only reading that turns scanner output into professional output.
- Write your own template for your own policy. The thirteen-line shape above is the whole grammar: id, severity, description, one request, one matcher. Plant the matching condition on your lab, fire it, watch it hit, then remove the condition and watch it hold fire. That pair of runs is your first opinion, executed twice, both correct.
- The subset audit. Pick any tag, list its templates, and read three at random. Note the severities, the matchers' strictness, the dates in the metadata. You now know more about that tag's worldview than most of its users, and the note is your defense when a client asks why a row was in your report: because I read the opinion and agreed.
Reveal the answer
The opinion card, template-writing in one page, the grammar plus the judgment calls:
id: your-policy-name # the finding's name in every report it reaches
info:
name: Human name
author: you
severity: high # YOUR call. The library's labels are strangers'
description: Why this matters, one line, because a finding
without a why is homework (lesson 044's law, template edition)
http:
- method: GET
path:
- "{{BaseURL}}/the-path-or-pattern"
matchers:
- type: status
status: [200]
# stricter: and= requires all matchers; add a word or regex
# matcher for the body when a bare 200 is too loose
The three judgment calls every template author makes, and you now make: the matcher's strictness, a bare 200 finds existing, a 200-plus-regex finds meaning, and loose matchers are how false positives are born. The severity, which should encode consequence in the client's world, not impressiveness in yours, 044's ranking law in one field. And the scope of the path, one exact file is a policy, a fuzzed family of paths is a patrol, and the second belongs in the fuzzer's world with 058's calibration, not here.
Where this leaves the tier's automation story, one paragraph. The scanner gave you testimony at machine speed. The baseline gave it memory. The fuzzer gave your questions a machine's patience. The template gives your judgment a machine's speed, and that is the last fusion: opinion, written down, run everywhere, held to the same fire discipline you hold yourself to. The next lesson is the map of when to automate at all and what it costs you when the tool lies, and the two after it close the tier the way Live Fire closed, with the human in the chair.
What this lesson does not claim
Templates are opinions, and opinions age. The library's thirteen thousand include stale ones, wrong ones, and severity calls you should override, and the update stream fixes some and ships others. Running nuclei is not a clearance, a compliance checkbox, or a pentest: it is one instrument from this tier's bench, aimed by your subsets, judged by your readings, extended by your templates, and bounded by the same three cards from 054 through 056 that bound every automated thing this tier taught. The machine now carries your opinions at machine speed. What it still does not carry, now or ever, is the responsibility for them. That stayed in your seat, where the whole tier has been aiming you.