Open source

Command-line tools for finding what an organisation exposes. They map its hosts, probe what answers on them, crawl the endpoints behind those and detect vulnerabilities across the result. The scanners read targets on stdin and write one result per line, so they chain with a pipe. We run them in our own research and products, so they stay maintained.

go install -v github.com/projectdiscovery/pdtm/cmd/pdtm@latest && pdtm -install-all

Mapping

Mapping starts from an organisation or a domain and ends with a resolved list of the hosts under it. No single source is complete, so query several and take the union.

subfinder queries passive sources: certificate transparency, passive DNS, search engines and the APIs you hold keys for. API keys go in provider-config.yaml. -all queries every source, not only the fast ones; -recursive keeps only the sources that can enumerate under a subdomain.

chaos-client returns subdomains from our DNS dataset of public bug bounty programs. uncover runs one query across Shodan, Censys, FOFA and a dozen other engines and returns host:port.

alterx guesses subdomains no source lists. It reads the subdomains found so far and writes permutations of them, dev-api and api-staging from api; -enrich adds the words it sees in the input to its pattern list. shuffledns guesses from a wordlist instead: -mode bruteforce resolves every word under a domain over massdns and discards the wildcard answers.

asnmap turns an organisation name, ASN, IP or domain into its announced ranges and mapcidr expands them to addresses; -shuffle-ip randomises the order so a scan does not walk a range sequentially. cdncheck marks the addresses that belong to a CDN, WAF or cloud provider rather than an origin; -resp prints the provider beside each and -exclude drops them so a scan reaches only origins.

Pipe the union into dnsx to resolve it. -a asks for A records and -cname or -mx for another type, -r takes your own resolvers, -resp prints the answer beside the subdomain, and -silent keeps stdout to results only.

acme.compassivechaossearchapi.acme.com192.0.2.7cdn.acme.comcnamevpn.acme.com203.0.113.9dev-old.acme.com198.51.100.24
subfinder -d acme.com -all -silent | alterx -silent | dnsx -silent -a -resp
  • subfinderTakes a domain, returns one subdomain per line.
  • chaos-clientTakes a domain, returns its known subdomains.
  • uncoverTakes a query, returns host:port.
  • alterxTakes subdomains, returns permutations to resolve.
  • shufflednsTakes a domain and a wordlist, returns the subdomains that resolve.
  • asnmapTakes an organisation name, ASN, IP or domain, returns the CIDRs it announces.
  • mapcidrTakes CIDRs, returns addresses or ranges.
  • cdncheckTakes IPs, returns the CDN, WAF or cloud provider in front of each.
  • dnsxTakes subdomains, returns the record type you ask for.

Probing

Probing takes the resolved hosts and records which ports are open, what service answers on each and what its certificate says.

naabu scans with CONNECT by default; -s s switches to SYN, which needs root. -top-ports 100 scans the hundred most common ports, -top-ports 1000 the thousand, and -p - all of them. -rate caps packets per second.

httpx probes each host over HTTPS and HTTP. -sc, -title, -cl and -location add the status code, title, content length and redirect target; -tech-detect adds the technologies it recognises, -screenshot saves a headless capture, and -json emits every field per host.

tlsx reads the certificate on each host. -san and -cn print the names in it, including hosts the DNS sources missed. -ex, -ss and -mm flag expired, self-signed and mismatched certificates. -ce lists the ciphers the server accepts.

hostportservicecertificate192.0.2.7443nginxR3 · 41d203.0.113.9443pulse secureself-signed198.51.100.248443jenkinsexpired
naabu -host 203.0.113.0/24 -top-ports 1000 -rate 2000 -silent \
    | httpx -silent -json -tech-detect
  • naabuTakes hosts or CIDRs, returns one open host:port per line.
  • httpxTakes hosts, returns status, title, content length and technologies for each one that answers.
  • tlsxTakes hosts, returns issuer, expiry and the names in the certificate.

Crawling

Crawling finds the endpoints behind a URL: the links on each page, the routes inside its JavaScript, the requests it makes once you are logged in and the endpoints its forms submit to.

katana crawls with a plain HTTP client by default and with a headless browser when you pass -headless, which runs the JavaScript and sees the routes it creates. -js-crawl parses every script it downloads for paths and API endpoints, and -known-files all pulls robots.txt and sitemap.xml.

-depth sets how many links deep it follows. -field-scope rdn, the default, keeps the crawl inside the root domain; fqdn restricts it to the exact host, and -crawl-scope takes a regex. -H passes a cookie or Authorization header so it crawls as a logged-in user, and -aff fills and submits the forms it finds.

-jsonl writes one line per endpoint with the method, the URL and the response status. -output-template prints one field per line instead, such as {{url}} or {{path}}, for feeding the next tool.

checkout.acme.com/login/cart/accountapp.js/api/cart/apply-coupon/api/v2/orders/{id}/internal/feature-flags/admin/reports
Highlighted: endpoints found only in the JavaScript bundle.
katana -u https://checkout.acme.com -headless -js-crawl -depth 3 \
    -H "Cookie: session=…" -jsonl
  • katanaTakes URLs, returns every endpoint it reaches.

Detection

Detection runs templates against what you found. A template is a YAML file: a request, matchers and a severity. Each match is a finding with the request that proved it.

nuclei reads targets from -l or stdin and runs the templates you select. -t takes a file or directory, -tags and -severity filter the public set, and -id runs one template by name. -rate-limit caps requests per second and -c sets how many templates run in parallel. -jsonl writes one line per match with the full request and response.

The public templates install on first run and update on each run unless you pass -duc. The set is written by the community, reviewed and signed by our template team; see Community. A template you write for your own target uses the same syntax; -t points nuclei at it and -validate checks it before a run.

Some bugs never show in the response, such as blind SSRF or out-of-band XXE. interactsh hands out unique hostnames for templates to use and reports the DNS, HTTP and SMTP interactions they receive. nuclei uses the public servers by default; -iserver and -itoken point it at an interactsh-server you run yourself.

vulnx looks up a CVE in our vulnerability index: the affected products, EPSS score, KEV status, and whether a public exploit or a template exists. It takes an id or a free-text query, reads ids on stdin, and --json prints the record.

templatestargetsnucleicve-2024-3400jenkins-loginblind-ssrfcors-misconfig
Dashed: confirmed through an out-of-band callback.
httpx -l hosts.txt -silent \
    | nuclei -t ~/my-templates -t http/cves/ -rate-limit 100 -jsonl
  • nucleiTakes URLs or hosts, returns one finding per match.
  • nuclei-templatesThe templates nuclei loads by default, updated on every run.
  • interactshHands out unique hostnames, reports the DNS, HTTP and SMTP interactions they receive.
  • vulnxTakes a CVE id or a query, returns the record.

Chaining tools

The stages join with a pipe, and anything that reads and writes lines fits between two tools. -silent keeps stdout to results; -json writes each result as a JSON object, spelled -jsonl in katana and nuclei.

subfinder -d acme.com -silent | httpx -silent | nuclei -severity high,critical -jsonl

subfinder emits one subdomain per line; httpx keeps the ones that answer and passes the URL; nuclei runs the high and critical templates against each.

katana -u https://checkout.acme.com -jsonl \
    | jq -r 'select(.response.status_code==200) | .request.endpoint' \
    | nuclei -t http/exposures/ -jsonl

katana emits one JSONL record per endpoint; jq keeps the endpoints that returned 200; nuclei runs the exposure templates against them.

Three tools sit around a pipeline. notify posts any tool’s output to Slack, Discord, Telegram or a webhook. proxify sits between a tool and its target, logs every request and response to a JSONL file with -output and rewrites them with -request-match-replace-dsl. pdtm installs and updates the binaries.

  • notifyReads stdin, posts each line to Slack, Discord, Telegram or a webhook.
  • proxifySits between a tool and its target; captures, replays and rewrites its traffic.
  • pdtmInstalls and updates every tool on this page.

Agent setup

The block below is this page in the form an agent reads: the install command, one line per tool, the flags that make output parseable and one pipeline. Paste it into Claude Code, Codex, Cursor or any agent, or point the agent at docs.projectdiscovery.io/tools for the full reference.

# ProjectDiscovery tools: context for an agent

Install the toolchain (Go 1.25+):
  go install -v github.com/projectdiscovery/pdtm/cmd/pdtm@latest && pdtm -install-all

subfinder, dnsx, naabu, httpx, katana and nuclei read targets from stdin or -l
(subfinder: -dL) and are non-interactive. Seeds: subfinder -d domain, katana -u url,
naabu -host cidr. uncover and vulnx take a query; interactsh-client takes no targets.
-silent keeps stdout to results only. -json writes one JSON object per line
(katana and nuclei: -jsonl; vulnx: --json).

Tools:
  subfinder   passive subdomain enumeration        subfinder -d example.com -silent
  dnsx        DNS resolution and record lookup      dnsx -silent -a -resp
  naabu       port scanning                         naabu -host 203.0.113.0/24 -silent
  httpx       HTTP probing, titles, tech, status    httpx -silent -json
  katana      web crawling, endpoints, forms        katana -u https://example.com -jsonl
  nuclei      template-based vulnerability scanning nuclei -severity high,critical -jsonl
  uncover     search engines for exposed hosts      uncover -q 'ssl:"example.com"'
  vulnx       CVE lookup, EPSS, KEV, exploits       vulnx id CVE-2024-3400 --json
  interactsh  out-of-band callback server/client    interactsh-client -json

A typical pipeline:
  subfinder -d example.com -silent | httpx -silent -json | nuclei -severity high,critical -jsonl

Scan only assets you are authorised to test.
nuclei downloads new templates on each run; nuclei -update-templates forces it.
Docs: https://docs.projectdiscovery.io

Community

The templates nuclei runs live in a public repository, nuclei-templates. Anyone can add one; we review, validate and sign every template before it reaches an install.

The repository

nuclei-templates is the set nuclei loads by default: about 13,600 templates, most of them HTTP, and about 4,400 of them cover a CVE. -tags kev,vkev selects the ones on the CISA and VulnCheck known-exploited lists.

Templates come from the community and from our own template team; about 1,300 people have authored one. nuclei and nuclei-templates are MIT licensed.

Contributing

Fork the repository, add one template and open a pull request. It needs an id, a name of the form Vendor Product Version - Vulnerability, an author, a CVSS-based severity, a description and a reference. We ask for a proof of concept that exercises the vulnerability and more than one matcher; version-only detection is not accepted.

The pull request checklist asks you to confirm the template fired on a vulnerable host and stayed quiet on a patched one; redacted nuclei -debug output speeds the review. Vulnerable hosts are never posted publicly; share them with us on Discord, which is also where templates get drafted when an exploit trends and where the maintainers answer questions. To ask for a template rather than write one, open a Request Template issue on GitHub; some carry a Bounty label.

Review

Every pull request runs yamllint and nuclei -validate, and a weak-matcher check fires the changed templates at a honeypot and comments if anything matches. A reviewer on the template team then checks the matchers, metadata and severity and tests the template against a vulnerable host where one is available.

On merge, CI signs the template with our certificate and it ships in the next release, about every three weeks. nuclei downloads each release on its next run.

From the NVD entry to a merged template, WordPress core CVE-2026-63030 took about six hours and Citrix NetScaler CVE-2026-3055 six days. Gitea CVE-2026-60004 had a template three weeks before NVD published it.

exploit trendstemplate prreview · mergereleaseinstalls update