├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md ├── auto_assign.yml ├── dependabot.yml ├── release.yml └── workflows │ ├── auto-merge.yaml │ ├── compat-checks.yaml │ ├── generate-docs.yaml │ ├── generate-pgo.yaml │ ├── govulncheck.yaml │ ├── perf-regression.yaml │ ├── perf-test.yaml │ ├── release.yaml │ ├── stale.yaml │ └── tests.yaml ├── .gitignore ├── .goreleaser.yml ├── .run ├── DSLFunctionsIT.run.xml ├── IntegrationTests.run.xml ├── RegressionTests.run.xml └── UnitTests.run.xml ├── CONTRIBUTING.md ├── DEBUG.md ├── DESIGN.md ├── Dockerfile ├── Dockerfile.goreleaser ├── LICENSE.md ├── Makefile ├── README.md ├── README_CN.md ├── README_ES.md ├── README_ID.md ├── README_JP.md ├── README_KR.md ├── README_PT-BR.md ├── SYNTAX-REFERENCE.md ├── THANKS.md ├── cmd ├── docgen │ └── docgen.go ├── functional-test │ ├── main.go │ ├── run.sh │ ├── targets-1000.txt │ ├── targets-150.txt │ ├── targets-250.txt │ ├── targets.txt │ └── testcases.txt ├── generate-checksum │ └── main.go ├── integration-test │ ├── code.go │ ├── custom-dir.go │ ├── dns.go │ ├── dsl.go │ ├── file.go │ ├── flow.go │ ├── fuzz.go │ ├── generic.go │ ├── headless.go │ ├── http.go │ ├── integration-test.go │ ├── interactsh.go │ ├── javascript.go │ ├── library.go │ ├── loader.go │ ├── matcher-status.go │ ├── multi.go │ ├── network.go │ ├── offline-http.go │ ├── profile-loader.go │ ├── ssl.go │ ├── template-dir.go │ ├── template-path.go │ ├── websocket.go │ ├── whois.go │ └── workflow.go ├── memogen │ ├── function.tpl │ └── memogen.go ├── nuclei │ ├── issue-tracker-config.yaml │ ├── main.go │ ├── main_test.go │ └── srv.yaml ├── scan-charts │ └── main.go ├── tmc │ ├── main.go │ └── types.go └── tools │ ├── fuzzplayground │ └── main.go │ └── signer │ └── main.go ├── examples ├── advanced │ └── advanced.go ├── simple │ └── simple.go └── with_speed_control │ └── main.go ├── gh_retry.sh ├── go.mod ├── go.sum ├── helm ├── Chart.yaml ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── hpa.yaml │ ├── interactsh-deployment.yaml │ ├── interactsh-ingress.yaml │ ├── interactsh-service.yaml │ ├── nuclei-configmap.yaml │ ├── nuclei-cron.yaml │ └── serviceaccount.yaml └── values.yaml ├── integration_tests ├── debug.sh ├── dsl │ ├── hide-version-warning.yaml │ └── show-version-warning.yaml ├── flow │ ├── conditional-flow-negative.yaml │ ├── conditional-flow.yaml │ ├── dns-ns-probe.yaml │ ├── flow-hide-matcher.yaml │ ├── iterate-one-value-flow.yaml │ └── iterate-values-flow.yaml ├── fuzz │ ├── fuzz-body-generic-sqli.yaml │ ├── fuzz-body-json-sqli.yaml │ ├── fuzz-body-multipart-form-sqli.yaml │ ├── fuzz-body-params-sqli.yaml │ ├── fuzz-body-xml-sqli.yaml │ ├── fuzz-cookie-error-sqli.yaml │ ├── fuzz-headless.yaml │ ├── fuzz-host-header-injection.yaml │ ├── fuzz-mode.yaml │ ├── fuzz-multi-mode.yaml │ ├── fuzz-path-sqli.yaml │ ├── fuzz-query-num-replace.yaml │ ├── fuzz-query.yaml │ ├── fuzz-type.yaml │ └── testData │ │ └── ginandjuice.proxify.yaml ├── generic │ └── auth │ │ └── certificate │ │ ├── assets │ │ ├── client.crt │ │ ├── client.key │ │ └── server.crt │ │ └── http-get.yaml ├── library │ ├── test.json │ └── test.yaml ├── loader │ ├── basic.yaml │ ├── condition-matched.yaml │ ├── excluded-template.yaml │ ├── get-headers.yaml │ ├── get.yaml │ ├── template-list.yaml │ └── workflow-list.yaml ├── profile-loader │ └── basic.yml ├── protocols │ ├── code │ │ ├── pre-condition.yaml │ │ ├── ps1-snippet.yaml │ │ ├── py-env-var.yaml │ │ ├── py-file.yaml │ │ ├── py-interactsh.yaml │ │ ├── py-nosig.yaml │ │ ├── py-snippet.yaml │ │ ├── pyfile.py │ │ └── unsigned.yaml │ ├── dns │ │ ├── a.yaml │ │ ├── aaaa.yaml │ │ ├── caa.yaml │ │ ├── cname-fingerprint.yaml │ │ ├── cname.yaml │ │ ├── dsl-matcher-variable.yaml │ │ ├── ns.yaml │ │ ├── payload.yaml │ │ ├── ptr.yaml │ │ ├── srv.yaml │ │ ├── tlsa.yaml │ │ ├── txt.yaml │ │ └── variables.yaml │ ├── file │ │ ├── data │ │ │ ├── test1.txt │ │ │ ├── test2.txt │ │ │ └── test3.txt │ │ ├── extract.yaml │ │ ├── matcher-with-and.yaml │ │ ├── matcher-with-nested-and.yaml │ │ └── matcher-with-or.yaml │ ├── headless │ │ ├── file-upload-negative.yaml │ │ ├── file-upload.yaml │ │ ├── headless-basic.yaml │ │ ├── headless-dsl.yaml │ │ ├── headless-extract-values.yaml │ │ ├── headless-header-action.yaml │ │ ├── headless-header-status-test.yaml │ │ ├── headless-local.yaml │ │ ├── headless-payloads.yaml │ │ ├── headless-self-contained.yaml │ │ ├── headless-waitevent.yaml │ │ └── variables.yaml │ ├── http │ │ ├── annotation-timeout.yaml │ │ ├── cl-body-with-header.yaml │ │ ├── cl-body-without-header.yaml │ │ ├── cli-with-constants.yaml │ │ ├── custom-attack-type.yaml │ │ ├── default-matcher-condition.yaml │ │ ├── disable-path-automerge.yaml │ │ ├── disable-redirects.yaml │ │ ├── dsl-functions.yaml │ │ ├── dsl-matcher-variable.yaml │ │ ├── get-all-ips.yaml │ │ ├── get-case-insensitive.yaml │ │ ├── get-headers.yaml │ │ ├── get-host-redirects.yaml │ │ ├── get-override-sni.yaml │ │ ├── get-query-string.yaml │ │ ├── get-redirects-chain-headers.yaml │ │ ├── get-redirects.yaml │ │ ├── get-sni-unsafe.yaml │ │ ├── get-sni.yaml │ │ ├── get-without-scheme.yaml │ │ ├── get.yaml │ │ ├── http-matcher-extractor-dy-extractor.yaml │ │ ├── http-paths.yaml │ │ ├── http-preprocessor.yaml │ │ ├── interactsh-requests-mc-and.yaml │ │ ├── interactsh-stop-at-first-match.yaml │ │ ├── interactsh.yaml │ │ ├── matcher-status.yaml │ │ ├── multi-http-var-sharing.yaml │ │ ├── multi-request.yaml │ │ ├── post-body.yaml │ │ ├── post-json-body.yaml │ │ ├── post-multipart-body.yaml │ │ ├── race-multiple.yaml │ │ ├── race-simple.yaml │ │ ├── raw-cookie-reuse.yaml │ │ ├── raw-dynamic-extractor.yaml │ │ ├── raw-get-query.yaml │ │ ├── raw-get.yaml │ │ ├── raw-path-single-slash.yaml │ │ ├── raw-path-trailing-slash.yaml │ │ ├── raw-payload.yaml │ │ ├── raw-post-body.yaml │ │ ├── raw-unsafe-path-single-slash.yaml │ │ ├── raw-unsafe-path.yaml │ │ ├── raw-unsafe-request.yaml │ │ ├── raw-unsafe-with-params.yaml │ │ ├── raw-with-params.yaml │ │ ├── redirect-match-url.yaml │ │ ├── request-condition-new.yaml │ │ ├── request-condition.yaml │ │ ├── self-contained-file-input.yaml │ │ ├── self-contained-with-params.yaml │ │ ├── self-contained-with-path.yaml │ │ ├── self-contained.yaml │ │ ├── stop-at-first-match-with-extractors.yaml │ │ ├── stop-at-first-match.yaml │ │ ├── variable-dsl-function.yaml │ │ └── variables.yaml │ ├── javascript │ │ ├── net-https.yaml │ │ ├── net-multi-step.yaml │ │ ├── redis-pass-brute.yaml │ │ └── ssh-server-fingerprint.yaml │ ├── keys │ │ ├── README.md │ │ ├── ci-private-key.pem │ │ └── ci.crt │ ├── multi │ │ ├── dynamic-values.yaml │ │ ├── evaluate-variables.yaml │ │ └── exported-response-vars.yaml │ ├── network │ │ ├── basic.yaml │ │ ├── hex.yaml │ │ ├── multi-step.yaml │ │ ├── net-https-timeout.yaml │ │ ├── net-https.yaml │ │ ├── network-port.yaml │ │ ├── same-address.yaml │ │ ├── self-contained.yaml │ │ └── variables.yaml │ ├── offlinehttp │ │ ├── data │ │ │ └── req-resp-with-http-keywords.txt │ │ ├── offline-allowed-paths.yaml │ │ ├── offline-raw.yaml │ │ └── rfc-req-resp.yaml │ ├── ssl │ │ ├── basic-ztls.yaml │ │ ├── basic.yaml │ │ ├── custom-cipher.yaml │ │ ├── custom-version.yaml │ │ ├── multi-req.yaml │ │ └── ssl-with-vars.yaml │ ├── websocket │ │ ├── basic.yaml │ │ ├── cswsh.yaml │ │ ├── no-cswsh.yaml │ │ └── path.yaml │ └── whois │ │ └── basic.yaml ├── run.sh ├── subdomains.txt ├── test-issue-tracker-config1.yaml ├── test-issue-tracker-config2.yaml └── workflow │ ├── basic.yaml │ ├── code-template-1.yaml │ ├── code-template-2.yaml │ ├── code-value-share-workflow.yaml │ ├── complex-conditions.yaml │ ├── condition-matched.yaml │ ├── condition-unmatched.yaml │ ├── dns-value-share-template-1.yaml │ ├── dns-value-share-template-2.yaml │ ├── dns-value-share-template-3.yaml │ ├── dns-value-share-workflow.yaml │ ├── headless-1.yaml │ ├── http-1.yaml │ ├── http-2.yaml │ ├── http-3.yaml │ ├── http-value-share-template-1.yaml │ ├── http-value-share-template-2.yaml │ ├── http-value-share-workflow.yaml │ ├── match-1.yaml │ ├── match-2.yaml │ ├── match-3.yaml │ ├── matcher-name.yaml │ ├── multimatch-value-share-template.yaml │ ├── multimatch-value-share-workflow.yaml │ ├── multiprotocol-value-share-template.yaml │ ├── multiprotocol-value-share-workflow.yaml │ ├── nomatch-1.yaml │ └── shared-cookie.yaml ├── internal ├── colorizer │ └── colorizer.go ├── httpapi │ └── apiendpoint.go ├── pdcp │ ├── utils.go │ └── writer.go ├── runner │ ├── banner.go │ ├── healthcheck.go │ ├── inputs.go │ ├── lazy.go │ ├── options.go │ ├── options_test.go │ ├── proxy.go │ ├── runner.go │ ├── runner_test.go │ └── templates.go └── server │ ├── dedupe.go │ ├── nuclei_sdk.go │ ├── requests_worker.go │ ├── scope │ ├── extensions.go │ ├── scope.go │ └── scope_test.go │ ├── server.go │ └── templates │ └── index.html ├── lib ├── README.md ├── config.go ├── example_test.go ├── helper.go ├── multi.go ├── sdk.go ├── sdk_private.go └── tests │ └── sdk_test.go ├── nuclei-jsonschema.json ├── pkg ├── authprovider │ ├── authx │ │ ├── basic_auth.go │ │ ├── bearer_auth.go │ │ ├── cookies_auth.go │ │ ├── dynamic.go │ │ ├── file.go │ │ ├── file_test.go │ │ ├── headers_auth.go │ │ ├── query_auth.go │ │ ├── strategy.go │ │ └── testData │ │ │ └── example-auth.yaml │ ├── file.go │ ├── interface.go │ └── multi.go ├── catalog │ ├── aws │ │ ├── catalog.go │ │ └── catalog_test.go │ ├── catalog.go │ ├── config │ │ ├── constants.go │ │ ├── ignorefile.go │ │ ├── nucleiconfig.go │ │ └── template.go │ ├── disk │ │ ├── catalog.go │ │ ├── find.go │ │ ├── known-files.go │ │ └── path.go │ └── loader │ │ ├── ai_loader.go │ │ ├── filter │ │ └── path_filter.go │ │ ├── loader.go │ │ ├── loader_test.go │ │ └── remote_loader.go ├── core │ ├── engine.go │ ├── engine_test.go │ ├── execute_options.go │ ├── executors.go │ ├── workflow_execute.go │ ├── workflow_execute_test.go │ └── workpool.go ├── external │ └── customtemplates │ │ ├── azure_blob.go │ │ ├── github.go │ │ ├── github_test.go │ │ ├── gitlab.go │ │ ├── s3.go │ │ └── templates_provider.go ├── fuzz │ ├── analyzers │ │ ├── analyzers.go │ │ └── time │ │ │ ├── analyzer.go │ │ │ ├── time_delay.go │ │ │ └── time_delay_test.go │ ├── component │ │ ├── body.go │ │ ├── body_test.go │ │ ├── component.go │ │ ├── cookie.go │ │ ├── cookie_test.go │ │ ├── headers.go │ │ ├── headers_test.go │ │ ├── path.go │ │ ├── path_test.go │ │ ├── query.go │ │ ├── query_test.go │ │ ├── value.go │ │ └── value_test.go │ ├── dataformat │ │ ├── dataformat.go │ │ ├── dataformat_test.go │ │ ├── form.go │ │ ├── json.go │ │ ├── kv.go │ │ ├── multipart.go │ │ ├── raw.go │ │ └── xml.go │ ├── doc.go │ ├── execute.go │ ├── frequency │ │ └── tracker.go │ ├── fuzz.go │ ├── fuzz_test.go │ ├── parts.go │ ├── parts_test.go │ ├── stats │ │ ├── db.go │ │ ├── db_test.go │ │ ├── simple.go │ │ └── stats.go │ └── type.go ├── input │ ├── README.md │ ├── formats │ │ ├── README.md │ │ ├── burp │ │ │ ├── burp.go │ │ │ └── burp_test.go │ │ ├── formats.go │ │ ├── json │ │ │ ├── json.go │ │ │ └── json_test.go │ │ ├── openapi │ │ │ ├── examples.go │ │ │ ├── generator.go │ │ │ ├── openapi.go │ │ │ └── openapi_test.go │ │ ├── swagger │ │ │ ├── swagger.go │ │ │ └── swagger_test.go │ │ ├── testdata │ │ │ ├── burp.xml │ │ │ ├── ginandjuice.proxify.json │ │ │ ├── ginandjuice.proxify.yaml │ │ │ ├── openapi.yaml │ │ │ ├── postman.json │ │ │ └── swagger.yaml │ │ └── yaml │ │ │ ├── multidoc.go │ │ │ └── multidoc_test.go │ ├── provider │ │ ├── chunked.go │ │ ├── http │ │ │ └── multiformat.go │ │ ├── interface.go │ │ ├── list │ │ │ ├── hmap.go │ │ │ ├── hmap_test.go │ │ │ ├── tests │ │ │ │ ├── AS134029.txt │ │ │ │ └── AS14421.txt │ │ │ └── utils.go │ │ └── simple.go │ ├── transform.go │ ├── transform_test.go │ └── types │ │ ├── http.go │ │ ├── http_test.go │ │ └── probe.go ├── installer │ ├── doc.go │ ├── template.go │ ├── template_test.go │ ├── util.go │ ├── versioncheck.go │ ├── versioncheck_test.go │ └── zipslip_unix_test.go ├── js │ ├── CONTRIBUTE.md │ ├── DESIGN.md │ ├── THANKS.md │ ├── compiler │ │ ├── compiler.go │ │ ├── compiler_test.go │ │ ├── init.go │ │ ├── non-pool.go │ │ └── pool.go │ ├── devtools │ │ ├── README.md │ │ ├── bindgen │ │ │ ├── INSTALL.md │ │ │ ├── README.md │ │ │ ├── cmd │ │ │ │ └── bindgen │ │ │ │ │ └── main.go │ │ │ ├── generator.go │ │ │ ├── output.go │ │ │ └── templates │ │ │ │ ├── go_class.tmpl │ │ │ │ ├── js_class.tmpl │ │ │ │ └── markdown_class.tmpl │ │ ├── scrapefuncs │ │ │ ├── README.md │ │ │ └── main.go │ │ └── tsgen │ │ │ ├── README.md │ │ │ ├── astutil.go │ │ │ ├── cmd │ │ │ └── tsgen │ │ │ │ ├── main.go │ │ │ │ └── tsmodule.go.tmpl │ │ │ ├── parser.go │ │ │ ├── scrape.go │ │ │ └── types.go │ ├── generated │ │ ├── README.md │ │ ├── go │ │ │ ├── libbytes │ │ │ │ └── bytes.go │ │ │ ├── libfs │ │ │ │ └── fs.go │ │ │ ├── libgoconsole │ │ │ │ └── goconsole.go │ │ │ ├── libikev2 │ │ │ │ └── ikev2.go │ │ │ ├── libkerberos │ │ │ │ └── kerberos.go │ │ │ ├── libldap │ │ │ │ └── ldap.go │ │ │ ├── libmssql │ │ │ │ └── mssql.go │ │ │ ├── libmysql │ │ │ │ └── mysql.go │ │ │ ├── libnet │ │ │ │ └── net.go │ │ │ ├── liboracle │ │ │ │ └── oracle.go │ │ │ ├── libpop3 │ │ │ │ └── pop3.go │ │ │ ├── libpostgres │ │ │ │ └── postgres.go │ │ │ ├── librdp │ │ │ │ └── rdp.go │ │ │ ├── libredis │ │ │ │ └── redis.go │ │ │ ├── librsync │ │ │ │ └── rsync.go │ │ │ ├── libsmb │ │ │ │ └── smb.go │ │ │ ├── libsmtp │ │ │ │ └── smtp.go │ │ │ ├── libssh │ │ │ │ └── ssh.go │ │ │ ├── libstructs │ │ │ │ └── structs.go │ │ │ ├── libtelnet │ │ │ │ └── telnet.go │ │ │ └── libvnc │ │ │ │ └── vnc.go │ │ └── ts │ │ │ ├── bytes.ts │ │ │ ├── fs.ts │ │ │ ├── goconsole.ts │ │ │ ├── ikev2.ts │ │ │ ├── index.ts │ │ │ ├── kerberos.ts │ │ │ ├── ldap.ts │ │ │ ├── mssql.ts │ │ │ ├── mysql.ts │ │ │ ├── net.ts │ │ │ ├── oracle.ts │ │ │ ├── pop3.ts │ │ │ ├── postgres.ts │ │ │ ├── rdp.ts │ │ │ ├── redis.ts │ │ │ ├── rsync.ts │ │ │ ├── smb.ts │ │ │ ├── smtp.ts │ │ │ ├── ssh.ts │ │ │ ├── structs.ts │ │ │ ├── telnet.ts │ │ │ └── vnc.ts │ ├── global │ │ ├── exports.js │ │ ├── helpers.go │ │ ├── js │ │ │ ├── active_directory.js │ │ │ └── dump.js │ │ ├── scripts.go │ │ └── scripts_test.go │ ├── gojs │ │ ├── gojs.go │ │ └── set.go │ ├── libs │ │ ├── LICENSE.md │ │ ├── bytes │ │ │ └── buffer.go │ │ ├── fs │ │ │ └── fs.go │ │ ├── goconsole │ │ │ └── log.go │ │ ├── ikev2 │ │ │ └── ikev2.go │ │ ├── kerberos │ │ │ ├── kerberosx.go │ │ │ └── sendtokdc.go │ │ ├── ldap │ │ │ ├── adenum.go │ │ │ ├── ldap.go │ │ │ └── utils.go │ │ ├── mssql │ │ │ ├── memo.mssql.go │ │ │ └── mssql.go │ │ ├── mysql │ │ │ ├── memo.mysql.go │ │ │ ├── memo.mysql_private.go │ │ │ ├── mysql.go │ │ │ └── mysql_private.go │ │ ├── net │ │ │ └── net.go │ │ ├── oracle │ │ │ ├── memo.oracle.go │ │ │ └── oracle.go │ │ ├── pop3 │ │ │ ├── memo.pop3.go │ │ │ └── pop3.go │ │ ├── postgres │ │ │ ├── memo.postgres.go │ │ │ └── postgres.go │ │ ├── rdp │ │ │ ├── memo.rdp.go │ │ │ └── rdp.go │ │ ├── redis │ │ │ ├── memo.redis.go │ │ │ └── redis.go │ │ ├── rsync │ │ │ ├── memo.rsync.go │ │ │ └── rsync.go │ │ ├── smb │ │ │ ├── memo.smb.go │ │ │ ├── memo.smb_private.go │ │ │ ├── memo.smbghost.go │ │ │ ├── smb.go │ │ │ ├── smb_private.go │ │ │ └── smbghost.go │ │ ├── smtp │ │ │ ├── msg.go │ │ │ └── smtp.go │ │ ├── ssh │ │ │ ├── memo.ssh.go │ │ │ └── ssh.go │ │ ├── structs │ │ │ ├── smbexploit.js │ │ │ └── structs.go │ │ ├── telnet │ │ │ ├── memo.telnet.go │ │ │ └── telnet.go │ │ └── vnc │ │ │ ├── memo.vnc.go │ │ │ └── vnc.go │ └── utils │ │ ├── nucleijs.go │ │ ├── pgwrap │ │ └── pgwrap.go │ │ └── util.go ├── keys │ ├── key.go │ └── nuclei.crt ├── loader │ ├── parser │ │ └── parser.go │ └── workflow │ │ └── workflow_loader.go ├── model │ ├── model.go │ ├── model_test.go │ ├── types │ │ ├── severity │ │ │ ├── severities.go │ │ │ ├── severity.go │ │ │ └── severity_test.go │ │ ├── stringslice │ │ │ ├── stringslice.go │ │ │ └── stringslice_raw.go │ │ └── userAgent │ │ │ └── user_agent.go │ └── worflow_loader.go ├── operators │ ├── common │ │ └── dsl │ │ │ ├── dsl.go │ │ │ └── dsl_test.go │ ├── extractors │ │ ├── compile.go │ │ ├── doc.go │ │ ├── extract.go │ │ ├── extract_test.go │ │ ├── extractor_types.go │ │ ├── extractors.go │ │ └── util.go │ ├── matchers │ │ ├── compile.go │ │ ├── doc.go │ │ ├── match.go │ │ ├── match_test.go │ │ ├── matchers.go │ │ ├── matchers_types.go │ │ ├── validate.go │ │ └── validate_test.go │ ├── operators.go │ └── operators_test.go ├── output │ ├── doc.go │ ├── file_output_writer.go │ ├── format_json.go │ ├── format_screen.go │ ├── multi_writer.go │ ├── output.go │ ├── output_stats.go │ ├── output_test.go │ ├── standard_writer.go │ └── stats │ │ ├── stats.go │ │ ├── stats_test.go │ │ └── waf │ │ ├── regexes.json │ │ ├── waf.go │ │ └── waf_test.go ├── progress │ ├── doc.go │ └── progress.go ├── projectfile │ ├── httputil.go │ └── project.go ├── protocols │ ├── code │ │ ├── code.go │ │ ├── code_test.go │ │ └── helpers.go │ ├── common │ │ ├── automaticscan │ │ │ ├── automaticscan.go │ │ │ ├── automaticscan_test.go │ │ │ ├── doc.go │ │ │ └── util.go │ │ ├── contextargs │ │ │ ├── contextargs.go │ │ │ ├── doc.go │ │ │ ├── metainput.go │ │ │ └── variables.go │ │ ├── expressions │ │ │ ├── expressions.go │ │ │ ├── expressions_test.go │ │ │ ├── variables.go │ │ │ └── variables_test.go │ │ ├── generators │ │ │ ├── attack_types.go │ │ │ ├── env.go │ │ │ ├── generators.go │ │ │ ├── generators_test.go │ │ │ ├── load.go │ │ │ ├── load_test.go │ │ │ ├── maps.go │ │ │ ├── maps_test.go │ │ │ ├── options.go │ │ │ ├── slice.go │ │ │ └── validate.go │ │ ├── globalmatchers │ │ │ └── globalmatchers.go │ │ ├── helpers │ │ │ ├── deserialization │ │ │ │ ├── deserialization.go │ │ │ │ ├── helpers.go │ │ │ │ ├── java.go │ │ │ │ └── testdata │ │ │ │ │ ├── Deserialize.java │ │ │ │ │ ├── README.md │ │ │ │ │ └── ValueObject.java │ │ │ ├── eventcreator │ │ │ │ └── eventcreator.go │ │ │ ├── responsehighlighter │ │ │ │ ├── hexdump.go │ │ │ │ ├── response_highlighter.go │ │ │ │ └── response_highlighter_test.go │ │ │ └── writer │ │ │ │ └── writer.go │ │ ├── hosterrorscache │ │ │ ├── hosterrorscache.go │ │ │ └── hosterrorscache_test.go │ │ ├── interactsh │ │ │ ├── const.go │ │ │ ├── interactsh.go │ │ │ └── options.go │ │ ├── marker │ │ │ └── marker.go │ │ ├── protocolinit │ │ │ └── init.go │ │ ├── protocolstate │ │ │ ├── file.go │ │ │ ├── headless.go │ │ │ ├── js.go │ │ │ ├── memguardian.go │ │ │ ├── memoizer.go │ │ │ └── state.go │ │ ├── randomip │ │ │ ├── randomip.go │ │ │ └── randomip_test.go │ │ ├── replacer │ │ │ ├── replacer.go │ │ │ └── replacer_test.go │ │ ├── uncover │ │ │ └── uncover.go │ │ ├── utils │ │ │ ├── excludematchers │ │ │ │ ├── excludematchers.go │ │ │ │ └── excludematchers_test.go │ │ │ └── vardump │ │ │ │ ├── dump.go │ │ │ │ ├── dump_test.go │ │ │ │ └── vars.go │ │ └── variables │ │ │ ├── doc.go │ │ │ ├── variables.go │ │ │ └── variables_test.go │ ├── dns │ │ ├── cluster.go │ │ ├── dns.go │ │ ├── dns_test.go │ │ ├── dns_types.go │ │ ├── dnsclientpool │ │ │ └── clientpool.go │ │ ├── operators.go │ │ ├── operators_test.go │ │ ├── request.go │ │ └── request_test.go │ ├── file │ │ ├── file.go │ │ ├── find.go │ │ ├── find_test.go │ │ ├── operators.go │ │ ├── operators_test.go │ │ ├── request.go │ │ └── request_test.go │ ├── headless │ │ ├── engine │ │ │ ├── action.go │ │ │ ├── action_types.go │ │ │ ├── engine.go │ │ │ ├── hijack.go │ │ │ ├── http_client.go │ │ │ ├── instance.go │ │ │ ├── page.go │ │ │ ├── page_actions.go │ │ │ ├── page_actions_test.go │ │ │ ├── rules.go │ │ │ └── util.go │ │ ├── headless.go │ │ ├── operators.go │ │ ├── operators_test.go │ │ └── request.go │ ├── http │ │ ├── build_request.go │ │ ├── build_request_test.go │ │ ├── cluster.go │ │ ├── cluster_test.go │ │ ├── http.go │ │ ├── http_method_types.go │ │ ├── http_test.go │ │ ├── httpclientpool │ │ │ ├── clientpool.go │ │ │ ├── errors.go │ │ │ └── options.go │ │ ├── httputils │ │ │ ├── misc.go │ │ │ └── spm.go │ │ ├── operators.go │ │ ├── operators_test.go │ │ ├── race │ │ │ └── syncedreadcloser.go │ │ ├── raw │ │ │ ├── doc.go │ │ │ ├── raw.go │ │ │ └── raw_test.go │ │ ├── request.go │ │ ├── request_annotations.go │ │ ├── request_annotations_test.go │ │ ├── request_condition.go │ │ ├── request_fuzz.go │ │ ├── request_generator.go │ │ ├── request_generator_test.go │ │ ├── request_test.go │ │ ├── signature.go │ │ ├── signer │ │ │ ├── aws-sign.go │ │ │ └── signer.go │ │ ├── signerpool │ │ │ └── signerpool.go │ │ ├── utils.go │ │ └── validate.go │ ├── javascript │ │ ├── js.go │ │ ├── js_test.go │ │ └── testcases │ │ │ ├── ms-sql-detect.yaml │ │ │ ├── redis-pass-brute.yaml │ │ │ └── ssh-server-fingerprint.yaml │ ├── network │ │ ├── network.go │ │ ├── network_input_types.go │ │ ├── network_test.go │ │ ├── networkclientpool │ │ │ └── clientpool.go │ │ ├── operators.go │ │ ├── operators_test.go │ │ ├── request.go │ │ └── request_test.go │ ├── offlinehttp │ │ ├── find.go │ │ ├── find_test.go │ │ ├── offlinehttp.go │ │ ├── operators.go │ │ ├── operators_test.go │ │ ├── read_response.go │ │ ├── read_response_test.go │ │ └── request.go │ ├── protocols.go │ ├── ssl │ │ ├── ssl.go │ │ └── ssl_test.go │ ├── utils │ │ ├── fields.go │ │ ├── http │ │ │ ├── requtils.go │ │ │ └── requtils_test.go │ │ ├── utils.go │ │ ├── utils_test.go │ │ ├── variables.go │ │ └── variables_test.go │ ├── websocket │ │ └── websocket.go │ └── whois │ │ ├── rdapclientpool │ │ └── clientpool.go │ │ └── whois.go ├── reporting │ ├── client.go │ ├── dedupe │ │ ├── dedupe.go │ │ └── dedupe_test.go │ ├── exporters │ │ ├── es │ │ │ └── elasticsearch.go │ │ ├── jsonexporter │ │ │ └── jsonexporter.go │ │ ├── jsonl │ │ │ └── jsonl.go │ │ ├── markdown │ │ │ ├── markdown.go │ │ │ └── util │ │ │ │ ├── markdown_formatter.go │ │ │ │ ├── markdown_utils.go │ │ │ │ └── markdown_utils_test.go │ │ ├── mongo │ │ │ └── mongo.go │ │ ├── sarif │ │ │ └── sarif.go │ │ └── splunk │ │ │ └── splunkhec.go │ ├── format │ │ ├── format.go │ │ ├── format_utils.go │ │ └── format_utils_test.go │ ├── options.go │ ├── reporting.go │ └── trackers │ │ ├── filters │ │ └── filters.go │ │ ├── gitea │ │ └── gitea.go │ │ ├── github │ │ └── github.go │ │ ├── gitlab │ │ └── gitlab.go │ │ ├── jira │ │ ├── jira.go │ │ └── jira_test.go │ │ └── linear │ │ ├── jsonutil │ │ └── jsonutil.go │ │ └── linear.go ├── scan │ ├── charts │ │ ├── charts.go │ │ └── echarts.go │ ├── events │ │ ├── scan_noop.go │ │ ├── stats_build.go │ │ └── utils.go │ └── scan_context.go ├── templates │ ├── cache.go │ ├── cache_test.go │ ├── cluster.go │ ├── cluster_test.go │ ├── compile.go │ ├── compile_test.go │ ├── doc.go │ ├── extensions │ │ └── extensions.go │ ├── log.go │ ├── log_test.go │ ├── parser.go │ ├── parser_config.go │ ├── parser_error.go │ ├── parser_stats.go │ ├── parser_test.go │ ├── parser_validate.go │ ├── preprocessors.go │ ├── signer │ │ ├── .nuclei-config │ │ │ └── nuclei │ │ │ │ └── .templates-config.json │ │ ├── default.go │ │ ├── handler.go │ │ ├── handler_test.go │ │ ├── tmpl_signer.go │ │ └── tmpl_signer_test.go │ ├── stats.go │ ├── tag_filter.go │ ├── tag_filter_test.go │ ├── template_sign.go │ ├── templates.go │ ├── templates_doc.go │ ├── templates_doc_examples.go │ ├── templates_test.go │ ├── tests │ │ ├── json-template.json │ │ ├── match-1.yaml │ │ ├── multiproto.json │ │ ├── multiproto.yaml │ │ ├── no-author.yaml │ │ ├── no-req.yaml │ │ ├── workflow-invalid.yaml │ │ └── workflow.yaml │ ├── types │ │ └── types.go │ └── workflows.go ├── testutils │ ├── fuzzplayground │ │ ├── db.go │ │ └── server.go │ ├── integration.go │ ├── testheadless │ │ ├── headless_local.go │ │ └── headless_runtime.go │ └── testutils.go ├── tmplexec │ ├── README.md │ ├── doc.go │ ├── exec.go │ ├── flow │ │ ├── README.md │ │ ├── builtin │ │ │ └── dedupe.go │ │ ├── doc.go │ │ ├── flow_executor.go │ │ ├── flow_executor_test.go │ │ ├── flow_internal.go │ │ ├── testcases │ │ │ ├── condition-flow-extractors.yaml │ │ │ ├── condition-flow-no-operators.yaml │ │ │ ├── condition-flow.yaml │ │ │ ├── nuclei-flow-dns-id.yaml │ │ │ ├── nuclei-flow-dns-prefix.yaml │ │ │ └── nuclei-flow-dns.yaml │ │ ├── util.go │ │ └── vm.go │ ├── generic │ │ └── exec.go │ ├── interface.go │ └── multiproto │ │ ├── README.md │ │ ├── doc.go │ │ ├── multi.go │ │ ├── multi_test.go │ │ └── testcases │ │ ├── multiprotodynamic.yaml │ │ └── multiprotowithprefix.yaml ├── types │ ├── interfaces.go │ ├── nucleierr │ │ └── kinds.go │ ├── resume.go │ ├── scanstrategy │ │ └── scan_strategy.go │ └── types.go ├── utils │ ├── expand │ │ └── expand.go │ ├── http_probe.go │ ├── index.go │ ├── insertion_ordered_map.go │ ├── insertion_ordered_map_test.go │ ├── json │ │ ├── doc.go │ │ ├── json.go │ │ ├── json_fallback.go │ │ ├── jsoncodec.go │ │ └── message.go │ ├── monitor │ │ ├── monitor.go │ │ └── monitor_test.go │ ├── stats │ │ ├── doc.go │ │ └── stats.go │ ├── template_path.go │ ├── utils.go │ ├── utils_test.go │ └── yaml │ │ ├── preprocess.go │ │ └── yaml_decode_wrapper.go └── workflows │ ├── doc.go │ ├── workflows.go │ └── workflows_test.go └── static ├── Join-Discord.png ├── check-nuclei-documentation.png ├── learn-more-button.png ├── nuclei-cover-image.png ├── nuclei-cover.png ├── nuclei-flow.jpg ├── nuclei-getting-started.png ├── nuclei-logo.png ├── nuclei-template-example.png ├── nuclei-templates-teamcity-example.png ├── nuclei-templates-teamcity.png ├── nuclei-write-your-first-template.png ├── projectdiscovery-browse-results.gif ├── regression-cycle.md ├── regression-with-nuclei.jpg └── teamcity-example.png /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | 3 | contact_links: 4 | 5 | - name: Ask an question / advise on using nuclei 6 | url: https://github.com/projectdiscovery/nuclei/discussions/categories/q-a 7 | about: Ask a question or request support for using nuclei 8 | 9 | - name: Share idea / feature to discuss for nuclei 10 | url: https://github.com/projectdiscovery/nuclei/discussions/categories/ideas 11 | about: Share idea / feature to discuss for nuclei 12 | 13 | - name: Connect with PD Team (Discord) 14 | url: https://discord.gg/projectdiscovery 15 | about: Connect with PD Team for direct communication -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed changes 2 | 3 | 4 | 5 | 6 | ## Checklist 7 | 8 | 9 | 10 | - [ ] Pull request is created against the [dev](https://github.com/projectdiscovery/nuclei/tree/dev) branch 11 | - [ ] All checks passed (lint, unit/integration/regression tests etc.) with my changes 12 | - [ ] I have added tests that prove my fix is effective or that my feature works 13 | - [ ] I have added necessary documentation (if appropriate) -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | addReviewers: true 2 | reviewers: 3 | - dogancanbakir 4 | - dwisiswant0 5 | 6 | numberOfReviewers: 1 7 | skipKeywords: 8 | - '@dependabot' -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | authors: 4 | - dependabot 5 | categories: 6 | - title: 🎉 New Features 7 | labels: 8 | - "Type: Enhancement" 9 | - title: 🐞 Bug Fixes 10 | labels: 11 | - "Type: Bug" 12 | - title: 🔨 Maintenance 13 | labels: 14 | - "Type: Maintenance" 15 | - title: Other Changes 16 | labels: 17 | - "*" -------------------------------------------------------------------------------- /.github/workflows/auto-merge.yaml: -------------------------------------------------------------------------------- 1 | name: 🤖 Auto Merge 2 | 3 | on: 4 | pull_request_review: 5 | types: [submitted] 6 | workflow_run: 7 | workflows: ["♾️ Compatibility Check"] 8 | types: 9 | - completed 10 | 11 | permissions: 12 | pull-requests: write 13 | issues: write 14 | repository-projects: write 15 | 16 | jobs: 17 | auto-merge: 18 | runs-on: ubuntu-latest 19 | if: github.actor == 'dependabot[bot]' 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | token: ${{ secrets.DEPENDABOT_PAT }} 24 | 25 | - uses: ahmadnassri/action-dependabot-auto-merge@v2 26 | with: 27 | github-token: ${{ secrets.DEPENDABOT_PAT }} 28 | target: all -------------------------------------------------------------------------------- /.github/workflows/compat-checks.yaml: -------------------------------------------------------------------------------- 1 | name: ♾️ Compatibility Checks 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize] 6 | branches: 7 | - dev 8 | 9 | jobs: 10 | check: 11 | if: github.actor == 'dependabot[bot]' 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: projectdiscovery/actions/setup/go/compat-checks@v1 18 | with: 19 | release-test: true 20 | -------------------------------------------------------------------------------- /.github/workflows/generate-docs.yaml: -------------------------------------------------------------------------------- 1 | name: ⏰ Generate Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | workflow_dispatch: 8 | 9 | jobs: 10 | publish-docs: 11 | if: "${{ !endsWith(github.actor, '[bot]') }}" 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: projectdiscovery/actions/setup/go@v1 16 | - uses: projectdiscovery/actions/setup/git@v1 17 | - run: make syntax-docs 18 | - run: git status -s | wc -l | xargs -I {} echo CHANGES={} >> $GITHUB_OUTPUT 19 | id: status 20 | - uses: projectdiscovery/actions/commit@v1 21 | if: steps.status.outputs.CHANGES > 0 22 | with: 23 | files: | 24 | SYNTAX-REFERENCE.md 25 | nuclei-jsonschema.json 26 | message: 'docs: update syntax & JSON schema 🤖' 27 | - run: git push origin $GITHUB_REF 28 | -------------------------------------------------------------------------------- /.github/workflows/govulncheck.yaml: -------------------------------------------------------------------------------- 1 | name: 🐛 govulncheck 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 0' # Weekly 6 | workflow_dispatch: 7 | 8 | jobs: 9 | govulncheck: 10 | runs-on: ubuntu-latest 11 | if: github.repository == 'projectdiscovery/nuclei' 12 | permissions: 13 | actions: read 14 | contents: read 15 | security-events: write 16 | env: 17 | OUTPUT: "/tmp/results.sarif" 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: projectdiscovery/actions/setup/go@v1 21 | - run: go install golang.org/x/vuln/cmd/govulncheck@latest 22 | - run: govulncheck -scan package -format sarif ./... > $OUTPUT 23 | - uses: github/codeql-action/upload-sarif@v3 24 | with: 25 | sarif_file: "${{ env.OUTPUT }}" 26 | category: "govulncheck" 27 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: 🎉 Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest-16-cores 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | - uses: projectdiscovery/actions/setup/go@v1 17 | - uses: docker/login-action@v3 18 | with: 19 | username: ${{ secrets.DOCKER_USERNAME }} 20 | password: ${{ secrets.DOCKER_TOKEN }} 21 | - uses: projectdiscovery/actions/goreleaser@v1 22 | with: 23 | release: true 24 | env: 25 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 26 | SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}" 27 | DISCORD_WEBHOOK_ID: "${{ secrets.DISCORD_WEBHOOK_ID }}" 28 | DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}" 29 | -------------------------------------------------------------------------------- /.run/DSLFunctionsIT.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.run/UnitTests.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build 2 | FROM golang:1.23-alpine AS builder 3 | 4 | RUN apk add build-base 5 | WORKDIR /app 6 | COPY . /app 7 | RUN make verify 8 | RUN make build 9 | 10 | # Release 11 | FROM alpine:latest 12 | 13 | RUN apk add --no-cache bind-tools chromium ca-certificates 14 | COPY --from=builder /app/bin/nuclei /usr/local/bin/ 15 | 16 | ENTRYPOINT ["nuclei"] 17 | -------------------------------------------------------------------------------- /Dockerfile.goreleaser: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | LABEL org.opencontainers.image.authors="ProjectDiscovery" 4 | LABEL org.opencontainers.image.description="Nuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations." 5 | LABEL org.opencontainers.image.licenses="MIT" 6 | LABEL org.opencontainers.image.title="nuclei" 7 | LABEL org.opencontainers.image.url="https://github.com/projectdiscovery/nuclei" 8 | 9 | RUN apk add --no-cache bind-tools chromium ca-certificates 10 | COPY nuclei /usr/local/bin/ 11 | 12 | ENTRYPOINT ["nuclei"] -------------------------------------------------------------------------------- /cmd/functional-test/targets.txt: -------------------------------------------------------------------------------- 1 | scanme.sh 2 | scanme.sh?a=1 3 | scanme.sh?a=2 4 | scanme.sh?a=3 -------------------------------------------------------------------------------- /cmd/integration-test/interactsh.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import osutils "github.com/projectdiscovery/utils/os" 4 | 5 | // All Interactsh related testcases 6 | var interactshTestCases = []TestCaseInfo{ 7 | {Path: "protocols/http/interactsh.yaml", TestCase: &httpInteractshRequest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, 8 | {Path: "protocols/http/interactsh-stop-at-first-match.yaml", TestCase: &httpInteractshStopAtFirstMatchRequest{}, DisableOn: func() bool { return true }}, // disable this test for now 9 | {Path: "protocols/http/default-matcher-condition.yaml", TestCase: &httpDefaultMatcherCondition{}, DisableOn: func() bool { return true }}, 10 | {Path: "protocols/http/interactsh-requests-mc-and.yaml", TestCase: &httpInteractshRequestsWithMCAnd{}}, 11 | } 12 | -------------------------------------------------------------------------------- /cmd/integration-test/multi.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/testutils" 5 | ) 6 | 7 | var multiProtoTestcases = []TestCaseInfo{ 8 | {Path: "protocols/multi/dynamic-values.yaml", TestCase: &multiProtoDynamicExtractor{}}, 9 | {Path: "protocols/multi/evaluate-variables.yaml", TestCase: &multiProtoDynamicExtractor{}}, 10 | {Path: "protocols/multi/exported-response-vars.yaml", TestCase: &multiProtoDynamicExtractor{}}, 11 | } 12 | 13 | type multiProtoDynamicExtractor struct{} 14 | 15 | // Execute executes a test case and returns an error if occurred 16 | func (h *multiProtoDynamicExtractor) Execute(templatePath string) error { 17 | results, err := testutils.RunNucleiTemplateAndGetResults(templatePath, "docs.projectdiscovery.io", debug) 18 | if err != nil { 19 | return err 20 | } 21 | return expectResultsCount(results, 1) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/integration-test/whois.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/testutils" 5 | ) 6 | 7 | var whoisTestCases = []TestCaseInfo{ 8 | {Path: "protocols/whois/basic.yaml", TestCase: &whoisBasic{}}, 9 | } 10 | 11 | type whoisBasic struct{} 12 | 13 | // Execute executes a test case and returns an error if occurred 14 | func (h *whoisBasic) Execute(filePath string) error { 15 | results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "https://example.com", debug) 16 | if err != nil { 17 | return err 18 | } 19 | return expectResultsCount(results, 1) 20 | } 21 | -------------------------------------------------------------------------------- /cmd/memogen/function.tpl: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package {{.SourcePackage}} 3 | 4 | import ( 5 | "github.com/projectdiscovery/utils/memoize" 6 | 7 | {{range .Imports}} 8 | {{.Name}} {{.Path}} 9 | {{end}} 10 | ) 11 | 12 | {{range .Functions}} 13 | {{ .SignatureWithPrefix "memoized" }} { 14 | hash := "{{ .Name }}" {{range .Params}} + ":" + fmt.Sprint({{.Name}}) {{end}} 15 | 16 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 17 | return {{.Name}}({{.ParamsNames}}) 18 | }) 19 | if err != nil { 20 | return {{.ResultFirstFieldDefaultValue}}, err 21 | } 22 | if value, ok := v.({{.ResultFirstFieldType}}); ok { 23 | return value, nil 24 | } 25 | 26 | return {{.ResultFirstFieldDefaultValue}}, errors.New("could not convert cached result") 27 | } 28 | {{end}} -------------------------------------------------------------------------------- /cmd/nuclei/srv.yaml: -------------------------------------------------------------------------------- 1 | id: basic-dns-a-example 2 | 3 | info: 4 | name: Test DNS A Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: SRV 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | part: all 17 | words: 18 | - "SRV" 19 | -------------------------------------------------------------------------------- /cmd/scan-charts/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/projectdiscovery/nuclei/v3/pkg/scan/charts" 7 | ) 8 | 9 | var ( 10 | dir string 11 | address string 12 | output string 13 | ) 14 | 15 | func main() { 16 | flag.StringVar(&dir, "dir", "", "directory to scan") 17 | flag.StringVar(&address, "address", ":9000", "address to run the server on") 18 | flag.StringVar(&output, "output", "", "output filename of generated html file") 19 | flag.Parse() 20 | 21 | if dir == "" { 22 | flag.Usage() 23 | return 24 | } 25 | 26 | server, err := charts.NewScanEventsCharts(dir) 27 | if err != nil { 28 | panic(err) 29 | } 30 | server.PrintInfo() 31 | 32 | if output != "" { 33 | if err = server.GenerateHTML(output); err != nil { 34 | panic(err) 35 | } 36 | return 37 | } 38 | 39 | server.Start(address) 40 | } 41 | -------------------------------------------------------------------------------- /cmd/tools/fuzzplayground/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | _ "github.com/mattn/go-sqlite3" 7 | "github.com/projectdiscovery/gologger" 8 | "github.com/projectdiscovery/nuclei/v3/pkg/testutils/fuzzplayground" 9 | ) 10 | 11 | var ( 12 | addr string 13 | ) 14 | 15 | func main() { 16 | flag.StringVar(&addr, "addr", "localhost:8082", "playground server address") 17 | flag.Parse() 18 | 19 | defer fuzzplayground.Cleanup() 20 | server := fuzzplayground.GetPlaygroundServer() 21 | defer server.Close() 22 | 23 | // Start the server 24 | if err := server.Start(addr); err != nil { 25 | gologger.Fatal().Msgf("Could not start server: %s\n", err) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/simple/simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | nuclei "github.com/projectdiscovery/nuclei/v3/lib" 7 | ) 8 | 9 | func main() { 10 | ne, err := nuclei.NewNucleiEngineCtx(context.Background(), 11 | nuclei.WithTemplateFilters(nuclei.TemplateFilters{Tags: []string{"oast"}}), 12 | nuclei.EnableStatsWithOpts(nuclei.StatsOptions{MetricServerPort: 6064}), // optionally enable metrics server for better observability 13 | ) 14 | if err != nil { 15 | panic(err) 16 | } 17 | // load targets and optionally probe non http/https targets 18 | ne.LoadTargets([]string{"http://honey.scanme.sh"}, false) 19 | err = ne.ExecuteWithCallback(nil) 20 | if err != nil { 21 | panic(err) 22 | } 23 | defer ne.Close() 24 | } 25 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: nuclei 3 | description: A Helm chart for Nuclei 4 | type: application 5 | version: 0.1.0 6 | appVersion: "2.5.7" 7 | -------------------------------------------------------------------------------- /helm/templates/interactsh-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ .Values.interactsh.service.name }} 5 | labels: 6 | {{- include "nuclei.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.interactsh.service.type }} 9 | ports: 10 | - port: {{ .Values.interactsh.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "nuclei.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /helm/templates/nuclei-configmap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: nuclei-conf 6 | data: 7 | nuclei.conf: |- 8 | {{ .Values.nuclei.config | indent 4 }} 9 | 10 | --- 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: nuclei-target-list 15 | data: 16 | target-list.txt: |- 17 | {{ .Values.nuclei.target_list | indent 4 }} 18 | -------------------------------------------------------------------------------- /helm/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "nuclei.serviceAccountName" . }} 6 | labels: 7 | {{- include "nuclei.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /integration_tests/dsl/hide-version-warning.yaml: -------------------------------------------------------------------------------- 1 | id: basic-example 2 | 3 | info: 4 | name: Test HTTP Template 5 | author: pdteam 6 | severity: info 7 | reference: | 8 | test case for default behaviour of version warning (dsl parsing error) 9 | 10 | http: 11 | - method: GET 12 | path: 13 | - "{{BaseURL}}" 14 | 15 | matchers: 16 | - type: dsl 17 | dsl: 18 | - compare_versions("GG", '< 4.8.5') -------------------------------------------------------------------------------- /integration_tests/dsl/show-version-warning.yaml: -------------------------------------------------------------------------------- 1 | id: basic-example 2 | 3 | info: 4 | name: Test HTTP Template 5 | author: pdteam 6 | severity: info 7 | reference: | 8 | test case where version warning is shown when env `SHOW_DSL_ERRORS=true` is set 9 | 10 | http: 11 | - method: GET 12 | path: 13 | - "{{BaseURL}}" 14 | 15 | matchers: 16 | - type: dsl 17 | dsl: 18 | - compare_versions("GG", '< 4.8.5') -------------------------------------------------------------------------------- /integration_tests/flow/conditional-flow-negative.yaml: -------------------------------------------------------------------------------- 1 | id: ghost-blog-detection 2 | info: 3 | name: Ghost blog detection 4 | author: pdteam 5 | severity: info 6 | 7 | 8 | flow: dns() && http() 9 | 10 | dns: 11 | - name: "{{FQDN}}" 12 | type: CNAME 13 | 14 | matchers: 15 | - type: word 16 | words: 17 | - "ghost.io" 18 | internal: true 19 | 20 | http: 21 | - method: GET 22 | path: 23 | - "{{BaseURL}}" 24 | 25 | matchers: 26 | - type: word 27 | words: 28 | - "ghost.io" -------------------------------------------------------------------------------- /integration_tests/flow/conditional-flow.yaml: -------------------------------------------------------------------------------- 1 | id: ghost-blog-detection 2 | info: 3 | name: Ghost blog detection 4 | author: pdteam 5 | severity: info 6 | 7 | 8 | flow: dns() && http() 9 | 10 | dns: 11 | - name: "{{FQDN}}" 12 | type: CNAME 13 | 14 | matchers: 15 | - type: word 16 | words: 17 | - ".vercel-dns.com" 18 | internal: true 19 | 20 | http: 21 | - method: GET 22 | path: 23 | - "{{BaseURL}}" 24 | 25 | matchers: 26 | - type: word 27 | words: 28 | - "html>" -------------------------------------------------------------------------------- /integration_tests/flow/flow-hide-matcher.yaml: -------------------------------------------------------------------------------- 1 | id: flow-hide-matcher 2 | 3 | info: 4 | name: Test Flow Hide Matcher 5 | author: pdteam 6 | severity: info 7 | description: In Template any matcher can be marked as internal which hides it from the output. 8 | 9 | flow: http(1) && http(2) 10 | 11 | http: 12 | - method: GET 13 | path: 14 | - "{{BaseURL}}" 15 | 16 | matchers: 17 | - type: word 18 | words: 19 | - ok 20 | internal: true 21 | 22 | - method: GET 23 | path: 24 | - "{{BaseURL}}" 25 | 26 | matchers: 27 | - type: word 28 | words: 29 | - "Failed event" -------------------------------------------------------------------------------- /integration_tests/flow/iterate-values-flow.yaml: -------------------------------------------------------------------------------- 1 | id: extract-emails 2 | 3 | info: 4 | name: Extract Email IDs from Response 5 | author: pdteam 6 | severity: info 7 | 8 | 9 | flow: | 10 | http(1) 11 | for(let email of template["emails"]) { 12 | set("email",email); 13 | http(2); 14 | } 15 | 16 | http: 17 | - method: GET 18 | path: 19 | - "{{BaseURL}}" 20 | 21 | extractors: 22 | - type: regex 23 | name: emails 24 | regex: 25 | - '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' 26 | internal: true 27 | 28 | - method: GET 29 | path: 30 | - "{{BaseURL}}/user/{{base64(email)}}" 31 | 32 | matchers: 33 | - type: word 34 | words: 35 | - "Welcome" 36 | 37 | extractors: 38 | - type: dsl 39 | name: email 40 | dsl: 41 | - email -------------------------------------------------------------------------------- /integration_tests/fuzz/fuzz-headless.yaml: -------------------------------------------------------------------------------- 1 | id: headless-query-fuzzing 2 | 3 | info: 4 | name: Example Query Fuzzing 5 | author: pdteam 6 | severity: info 7 | 8 | headless: 9 | - steps: 10 | - action: navigate 11 | args: 12 | url: "{{BaseURL}}" 13 | - action: waitload 14 | 15 | payloads: 16 | redirect: 17 | - "blog.com" 18 | - "portal.com" 19 | 20 | fuzzing: 21 | - part: query 22 | mode: single 23 | type: replace 24 | fuzz: 25 | - "https://{{redirect}}" 26 | 27 | matchers: 28 | - type: word 29 | part: body 30 | words: 31 | - "{{redirect}}" 32 | -------------------------------------------------------------------------------- /integration_tests/fuzz/fuzz-mode.yaml: -------------------------------------------------------------------------------- 1 | id: fuzz-query 2 | 3 | info: 4 | name: Basic Fuzz URL Query 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | fuzzing: 13 | - part: query 14 | type: postfix 15 | mode: multiple 16 | keys: ["id","name"] 17 | fuzz: ["fuzz-word"] 18 | matchers-condition: and 19 | matchers: 20 | - type: word 21 | part: body 22 | words: 23 | - "fuzz-word" 24 | - type: word 25 | part: header 26 | words: 27 | - "text/html" 28 | -------------------------------------------------------------------------------- /integration_tests/fuzz/fuzz-multi-mode.yaml: -------------------------------------------------------------------------------- 1 | id: fuzz-multi-mode-test 2 | 3 | info: 4 | name: multi-mode fuzzing test 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - payloads: 10 | inject: 11 | - nuclei-v1 12 | - nuclei-v2 13 | - nuclei-v3 14 | 15 | fuzzing: 16 | - part: header 17 | type: replace 18 | mode: multiple 19 | fuzz: 20 | X-Client-Id: "{{inject}}" 21 | X-Secret-Id: "{{inject}}" 22 | 23 | matchers-condition: or 24 | matchers: 25 | - type: word 26 | words: 27 | - "nuclei-v3" -------------------------------------------------------------------------------- /integration_tests/fuzz/fuzz-query.yaml: -------------------------------------------------------------------------------- 1 | id: fuzz-query 2 | 3 | info: 4 | name: Basic Fuzz URL Query 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | fuzzing: 13 | - part: query 14 | type: postfix 15 | mode: single 16 | keys: ["id"] 17 | fuzz: ["6842'\"><"] 18 | matchers-condition: and 19 | matchers: 20 | - type: word 21 | part: body 22 | words: 23 | - "6842'\"><" 24 | - type: word 25 | part: header 26 | words: 27 | - "text/html" 28 | -------------------------------------------------------------------------------- /integration_tests/fuzz/fuzz-type.yaml: -------------------------------------------------------------------------------- 1 | id: fuzz-type 2 | 3 | info: 4 | name: Basic Fuzz URL Query 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | fuzzing: 13 | - part: query 14 | type: postfix 15 | mode: single 16 | keys: ["id"] 17 | fuzz: ["fuzz-word"] 18 | matchers-condition: and 19 | matchers: 20 | - type: word 21 | part: body 22 | words: 23 | - "fuzz-word" 24 | - type: word 25 | part: header 26 | words: 27 | - "text/html" 28 | -------------------------------------------------------------------------------- /integration_tests/generic/auth/certificate/http-get.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-with-cert 2 | 3 | info: 4 | name: Basic GET with Cert 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "Hello" -------------------------------------------------------------------------------- /integration_tests/library/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "go-integration-test", 3 | "info": { 4 | "name": "Basic Go Integration Test", 5 | "author": "pdteam", 6 | "severity": "info" 7 | }, 8 | "requests": [ 9 | { 10 | "method": "GET", 11 | "path": [ 12 | "{{BaseURL}}" 13 | ], 14 | "headers": { 15 | "test": "nuclei" 16 | }, 17 | "matchers": [ 18 | { 19 | "type": "word", 20 | "words": [ 21 | "This is test headers matcher text" 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /integration_tests/library/test.yaml: -------------------------------------------------------------------------------- 1 | id: go-integration-test 2 | 3 | info: 4 | name: Basic Go Integration Test 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | headers: 13 | test: nuclei 14 | matchers: 15 | - type: word 16 | words: 17 | - "This is test headers matcher text" -------------------------------------------------------------------------------- /integration_tests/loader/basic.yaml: -------------------------------------------------------------------------------- 1 | id: workflow-example 2 | 3 | info: 4 | name: Test Workflow Template 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/match-1.yaml 10 | - template: workflow/match-2.yaml -------------------------------------------------------------------------------- /integration_tests/loader/condition-matched.yaml: -------------------------------------------------------------------------------- 1 | id: condition-matched-workflow 2 | 3 | info: 4 | name: Condition Matched Workflow 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/match-1.yaml 10 | subtemplates: 11 | - template: workflow/match-2.yaml -------------------------------------------------------------------------------- /integration_tests/loader/excluded-template.yaml: -------------------------------------------------------------------------------- 1 | id: excluded-template 2 | 3 | info: 4 | name: Basic Excluded Template 5 | author: pdteam 6 | severity: info 7 | tags: fuzz 8 | 9 | http: 10 | - method: GET 11 | path: 12 | - "{{BaseURL}}" 13 | matchers: 14 | - type: word 15 | words: 16 | - "This is test matcher text" -------------------------------------------------------------------------------- /integration_tests/loader/get-headers.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-headers 2 | 3 | info: 4 | name: Basic GET Headers Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | headers: 13 | test: nuclei 14 | matchers: 15 | - type: word 16 | words: 17 | - "This is test headers matcher text" -------------------------------------------------------------------------------- /integration_tests/loader/get.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "This is test matcher text" -------------------------------------------------------------------------------- /integration_tests/loader/template-list.yaml: -------------------------------------------------------------------------------- 1 | loader/get.yaml 2 | loader/get-headers.yaml 3 | -------------------------------------------------------------------------------- /integration_tests/loader/workflow-list.yaml: -------------------------------------------------------------------------------- 1 | loader/basic.yaml 2 | loader/condition-matched.yaml 3 | -------------------------------------------------------------------------------- /integration_tests/profile-loader/basic.yml: -------------------------------------------------------------------------------- 1 | tags: 2 | - kev -------------------------------------------------------------------------------- /integration_tests/protocols/code/pre-condition.yaml: -------------------------------------------------------------------------------- 1 | id: pre-condition-code 2 | 3 | info: 4 | name: example code template 5 | author: pdteam 6 | severity: info 7 | 8 | 9 | self-contained: true 10 | 11 | variables: 12 | OAST: "{{interactsh-url}}" 13 | 14 | code: 15 | - pre-condition: IsLinux() 16 | engine: 17 | - sh 18 | - bash 19 | source: | 20 | echo "$OAST" | base64 21 | 22 | matchers: 23 | - type: dsl 24 | dsl: 25 | - true 26 | # digest: 490a00463044022048c083c338c0195f5012122d40c1009d2e2030c583e56558e0d6249a41e6f3f4022070656adf748f4874018d7a01fce116db10a3acd1f9b03e12a83906fb625b5c50:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/protocols/code/ps1-snippet.yaml: -------------------------------------------------------------------------------- 1 | id: ps1-code-snippet 2 | 3 | info: 4 | name: ps1-code-snippet 5 | author: pdteam 6 | severity: info 7 | tags: code 8 | description: | 9 | ps1-code-snippet 10 | 11 | code: 12 | - engine: 13 | - powershell 14 | - powershell.exe 15 | args: 16 | - -ExecutionPolicy 17 | - Bypass 18 | - -File 19 | pattern: "*.ps1" 20 | source: | 21 | $stdin = [Console]::In 22 | $line = $stdin.ReadLine() 23 | Write-Host "hello from $line" 24 | 25 | matchers: 26 | - type: word 27 | words: 28 | - "hello from input" -------------------------------------------------------------------------------- /integration_tests/protocols/code/py-env-var.yaml: -------------------------------------------------------------------------------- 1 | id: py-code-snippet 2 | 3 | info: 4 | name: py-code-snippet 5 | author: pdteam 6 | severity: info 7 | tags: code 8 | description: | 9 | py-code-snippet 10 | 11 | code: 12 | - engine: 13 | - py 14 | - python3 15 | source: | 16 | import sys,os 17 | print("hello from " + sys.stdin.read() + " " + os.getenv('baz')) 18 | 19 | matchers: 20 | - type: word 21 | words: 22 | - "hello from input baz" 23 | # digest: 4b0a00483046022100cbbdb7214f669d111b671d271110872dc8af2ab41cf5c312b6e4f64126f55337022100a60547952a0c2bea58388f2d2effe8ad73cd6b6fc92e73eb3c8f88beab6105ec:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/protocols/code/py-file.yaml: -------------------------------------------------------------------------------- 1 | id: py-file 2 | 3 | info: 4 | name: py-file 5 | author: pdteam 6 | severity: info 7 | tags: code 8 | description: | 9 | py-file 10 | 11 | code: 12 | - engine: 13 | - py 14 | - python3 15 | source: protocols/code/pyfile.py 16 | 17 | matchers: 18 | - type: word 19 | words: 20 | - "hello from input" 21 | # digest: 4a0a00473045022032b81e8bb7475abf27639b0ced71355497166d664698021f26498e7031d62a23022100e99ccde578bfc0b658f16427ae9a3d18922849d3ba3e022032ea0d2a8e77fadb:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/protocols/code/py-interactsh.yaml: -------------------------------------------------------------------------------- 1 | id: testcode 2 | 3 | info: 4 | name: testcode 5 | author: testcode 6 | severity: info 7 | tags: code 8 | description: | 9 | testcode 10 | 11 | variables: 12 | i: "{{interactsh-url}}" 13 | 14 | code: 15 | - engine: 16 | - py 17 | - python3 18 | # Simulate interactsh interaction 19 | source: | 20 | import os 21 | from urllib.request import urlopen 22 | urlopen("http://" + os.getenv('i')) 23 | 24 | matchers: 25 | - type: word 26 | part: interactsh_protocol 27 | words: 28 | - "http" 29 | # digest: 4a0a0047304502201a5dd0eddfab4f02588a5a8ac1947a5fa41fed80b59d698ad5cc00456296efb6022100fe6e608e38c060964800f5f863a7cdc93f686f2d0f4b52854f73948b808b4511:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/protocols/code/py-nosig.yaml: -------------------------------------------------------------------------------- 1 | id: py-nosig 2 | 3 | info: 4 | name: py-nosig 5 | author: pdteam 6 | severity: info 7 | tags: code 8 | description: | 9 | Python code without signature 10 | 11 | code: 12 | - engine: 13 | - py 14 | - python3 15 | source: | 16 | print("py unsigned code") 17 | 18 | matchers: 19 | - type: word 20 | words: 21 | - "py unsigned code" -------------------------------------------------------------------------------- /integration_tests/protocols/code/py-snippet.yaml: -------------------------------------------------------------------------------- 1 | id: py-code-snippet 2 | 3 | info: 4 | name: py-code-snippet 5 | author: pdteam 6 | severity: info 7 | tags: code 8 | description: | 9 | py-code-snippet 10 | 11 | code: 12 | - engine: 13 | - py 14 | - python3 15 | - python 16 | source: | 17 | import sys 18 | print("hello from " + sys.stdin.read()) 19 | 20 | matchers: 21 | - type: word 22 | words: 23 | - "hello from input" 24 | # digest: 4b0a00483046022100ced1702728cc68f906c4c7d2c4d05ed071bfabee1e36eec7ebecbeca795a170c022100d20fd41796f130a8f9c4972fee85386d67d61eb5fc1119b1afe2a851eb2f3e65:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/protocols/code/pyfile.py: -------------------------------------------------------------------------------- 1 | import sys 2 | print("hello from " + sys.stdin.read()) -------------------------------------------------------------------------------- /integration_tests/protocols/code/unsigned.yaml: -------------------------------------------------------------------------------- 1 | id: unsigned-code-snippet 2 | 3 | info: 4 | name: unsigned-code-snippet 5 | author: pdteam 6 | severity: info 7 | tags: code 8 | description: | 9 | unsigned-code-snippet 10 | 11 | code: 12 | - engine: 13 | - py 14 | - python3 15 | source: | 16 | print("unsigned code") 17 | 18 | matchers: 19 | - type: word 20 | words: 21 | - "unsigned code" -------------------------------------------------------------------------------- /integration_tests/protocols/dns/a.yaml: -------------------------------------------------------------------------------- 1 | id: dns-a-query-example 2 | 3 | info: 4 | name: Test DNS A Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: A 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | words: 17 | - "1.1.1.1" 18 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/aaaa.yaml: -------------------------------------------------------------------------------- 1 | id: dns-aaaa-query-example 2 | 3 | info: 4 | name: Test DNS AAAA Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: AAAA 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | words: 17 | - "2606:4700:4700::1001" 18 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/caa.yaml: -------------------------------------------------------------------------------- 1 | id: caa-fingerprinting 2 | 3 | info: 4 | name: CAA Fingerprint 5 | author: pdteam 6 | severity: info 7 | tags: dns,caa 8 | 9 | dns: 10 | - name: "{{FQDN}}" 11 | type: CAA 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "IN\tCAA" 17 | 18 | extractors: 19 | - type: regex 20 | group: 1 21 | regex: 22 | - "IN\tCAA\t(.+)" -------------------------------------------------------------------------------- /integration_tests/protocols/dns/cname-fingerprint.yaml: -------------------------------------------------------------------------------- 1 | id: cname-fingerprint 2 | 3 | info: 4 | name: CNAME Fingerprint 5 | author: pdteam 6 | severity: info 7 | tags: dns,cname 8 | 9 | dns: 10 | - name: "{{FQDN}}" 11 | type: NS 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "IN\tCNAME" 17 | 18 | extractors: 19 | - type: regex 20 | group: 1 21 | regex: 22 | - "IN\tCNAME\t(.+)" 23 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/cname.yaml: -------------------------------------------------------------------------------- 1 | id: dns-cname-query-example 2 | 3 | info: 4 | name: Test DNS CNAME Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: CNAME 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | part: all 17 | words: 18 | - "CNAME" 19 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/dsl-matcher-variable.yaml: -------------------------------------------------------------------------------- 1 | id: dns-template 2 | 3 | info: 4 | name: basic dns template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: CNAME 11 | 12 | matchers: 13 | - type: dsl 14 | dsl: 15 | - "rcode == 0" 16 | 17 | extractors: 18 | - type: dsl 19 | dsl: 20 | - rcode 21 | - cname 22 | - a 23 | - aaaa -------------------------------------------------------------------------------- /integration_tests/protocols/dns/ns.yaml: -------------------------------------------------------------------------------- 1 | id: dns-ns-query-example 2 | 3 | info: 4 | name: Test DNS NS Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: NS 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | part: all 17 | words: 18 | - "NS" 19 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/payload.yaml: -------------------------------------------------------------------------------- 1 | id: dns-attack 2 | 3 | info: 4 | name: basic dns template 5 | author: pdteam 6 | severity: info 7 | 8 | 9 | dns: 10 | - name: "{{subdomain_wordlist}}.{{FQDN}}" 11 | type: A 12 | 13 | attack: batteringram 14 | payloads: 15 | subdomain_wordlist: 16 | - one 17 | - docs 18 | - drive 19 | 20 | matchers: 21 | - type: word 22 | words: 23 | - "IN\tA" 24 | 25 | extractors: 26 | - type: regex 27 | group: 1 28 | regex: 29 | - "IN\tA\t(.+)" 30 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/ptr.yaml: -------------------------------------------------------------------------------- 1 | id: ptr-fingerprint 2 | 3 | info: 4 | name: PTR Fingerprint 5 | author: pdteam 6 | severity: info 7 | tags: dns,ptr 8 | 9 | dns: 10 | - name: "{{FQDN}}" 11 | type: PTR 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "IN\tPTR" 17 | 18 | extractors: 19 | - type: regex 20 | group: 1 21 | regex: 22 | - "IN\tPTR\t(.+)" -------------------------------------------------------------------------------- /integration_tests/protocols/dns/srv.yaml: -------------------------------------------------------------------------------- 1 | id: dns-a-query-example 2 | 3 | info: 4 | name: Test DNS SRV Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: SRV 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | part: all 17 | words: 18 | - "SRV" 19 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/tlsa.yaml: -------------------------------------------------------------------------------- 1 | id: tlsa-fingerprinting 2 | 3 | info: 4 | name: TLSA Fingerprint 5 | author: pdteam 6 | severity: info 7 | tags: dns,tlsa 8 | 9 | dns: 10 | - name: "{{FQDN}}" 11 | type: TLSA 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "IN\tTLSA" 17 | 18 | extractors: 19 | - type: regex 20 | group: 1 21 | regex: 22 | - "IN\tTLSA\t(.+)" -------------------------------------------------------------------------------- /integration_tests/protocols/dns/txt.yaml: -------------------------------------------------------------------------------- 1 | id: dns-txt-query-example 2 | 3 | info: 4 | name: Test DNS TXT Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: TXT 11 | class: inet 12 | recursion: true 13 | retries: 3 14 | matchers: 15 | - type: word 16 | part: all 17 | words: 18 | - "TXT" 19 | -------------------------------------------------------------------------------- /integration_tests/protocols/dns/variables.yaml: -------------------------------------------------------------------------------- 1 | id: variables-example 2 | 3 | info: 4 | name: Variables Example 5 | author: pdteam 6 | severity: info 7 | 8 | variables: 9 | a1: "IN" 10 | 11 | dns: 12 | - name: "{{FQDN}}" 13 | type: A 14 | class: inet 15 | recursion: true 16 | retries: 3 17 | matchers: 18 | - type: word 19 | words: 20 | - "{{a1}}" -------------------------------------------------------------------------------- /integration_tests/protocols/file/data/test1.txt: -------------------------------------------------------------------------------- 1 | AAA 2 | BBB -------------------------------------------------------------------------------- /integration_tests/protocols/file/data/test2.txt: -------------------------------------------------------------------------------- 1 | CCC 2 | DDD -------------------------------------------------------------------------------- /integration_tests/protocols/file/data/test3.txt: -------------------------------------------------------------------------------- 1 | 11 EE 11 2 | 11 FF 11 -------------------------------------------------------------------------------- /integration_tests/protocols/file/extract.yaml: -------------------------------------------------------------------------------- 1 | id: file-extract 2 | 3 | info: 4 | name: File with Extractor 5 | author: pdteam 6 | severity: info 7 | tags: file 8 | 9 | file: 10 | - extensions: 11 | - all 12 | 13 | extractors: 14 | - type: regex 15 | regex: 16 | - "(?m)11\\s(EE|FF)\\s11" -------------------------------------------------------------------------------- /integration_tests/protocols/file/matcher-with-and.yaml: -------------------------------------------------------------------------------- 1 | id: file-matcher-with-and 2 | 3 | info: 4 | name: File Matcher With AND 5 | author: pdteam 6 | severity: info 7 | tags: file 8 | 9 | file: 10 | - extensions: 11 | - all 12 | 13 | matchers-condition: and 14 | matchers: 15 | - type: word 16 | words: 17 | - "CCC" 18 | - type: word 19 | words: 20 | - "DDD" -------------------------------------------------------------------------------- /integration_tests/protocols/file/matcher-with-nested-and.yaml: -------------------------------------------------------------------------------- 1 | id: file-matcher-with-nested-and 2 | 3 | info: 4 | name: File Matcher With nested AND 5 | author: pdteam 6 | severity: info 7 | tags: file 8 | 9 | file: 10 | - extensions: 11 | - all 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "CCC" 17 | - "DDD" 18 | condition: and -------------------------------------------------------------------------------- /integration_tests/protocols/file/matcher-with-or.yaml: -------------------------------------------------------------------------------- 1 | id: file-matcher-with-or 2 | 3 | info: 4 | name: File Matcher With OR 5 | author: pdteam 6 | severity: info 7 | tags: file 8 | 9 | file: 10 | - extensions: 11 | - all 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "AA" 17 | - type: word 18 | words: 19 | - "BB" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/file-upload-negative.yaml: -------------------------------------------------------------------------------- 1 | id: file-upload 2 | # template for testing when file upload is disabled 3 | info: 4 | name: Basic File Upload 5 | author: pdteam 6 | severity: info 7 | 8 | headless: 9 | - steps: 10 | - action: navigate 11 | args: 12 | url: "{{BaseURL}}" 13 | - action: waitload 14 | - action: files 15 | args: 16 | by: xpath 17 | xpath: /html/body/form/input[1] 18 | value: headless/file-upload.yaml 19 | - action: sleep 20 | args: 21 | duration: 2 22 | - action: click 23 | args: 24 | by: x 25 | xpath: /html/body/form/input[2] 26 | matchers: 27 | - type: word 28 | words: 29 | - "Basic File Upload" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/file-upload.yaml: -------------------------------------------------------------------------------- 1 | id: file-upload 2 | 3 | info: 4 | name: Basic File Upload 5 | author: pdteam 6 | severity: info 7 | 8 | headless: 9 | - steps: 10 | - action: navigate 11 | args: 12 | url: "{{BaseURL}}" 13 | - action: waitload 14 | - action: files 15 | args: 16 | by: xpath 17 | xpath: /html/body/form/input[1] 18 | value: protocols/headless/file-upload.yaml 19 | - action: sleep 20 | args: 21 | duration: 2 22 | - action: click 23 | args: 24 | by: x 25 | xpath: /html/body/form/input[2] 26 | matchers: 27 | - type: word 28 | words: 29 | - "Basic File Upload" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-basic.yaml: -------------------------------------------------------------------------------- 1 | id: headless-basic 2 | info: 3 | name: Headless Basic 4 | author: pdteam 5 | severity: info 6 | tags: headless 7 | 8 | headless: 9 | - steps: 10 | - action: navigate 11 | args: 12 | url: "{{BaseURL}}/" 13 | 14 | - action: waitload 15 | matchers: 16 | - type: word 17 | words: 18 | - "" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-dsl.yaml: -------------------------------------------------------------------------------- 1 | id: headless-dsl 2 | 3 | info: 4 | name: Headless DSL 5 | author: dwisiswant0 6 | severity: info 7 | tags: headless 8 | 9 | headless: 10 | - steps: 11 | - action: navigate 12 | args: 13 | url: "{{BaseURL}}/?_={{urlencode(concat('foo', '-', 'bar'))}}" 14 | - action: waitload 15 | matchers: 16 | - type: word 17 | words: 18 | - "foo-bar" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-extract-values.yaml: -------------------------------------------------------------------------------- 1 | 2 | id: headless-extract-values 3 | info: 4 | name: Headless Extract Value 5 | author: pdteam 6 | severity: info 7 | tags: headless 8 | 9 | headless: 10 | - steps: 11 | - action: navigate 12 | args: 13 | url: "{{BaseURL}}" 14 | - action: waitload 15 | # From headless/extract-urls.yaml 16 | - action: script 17 | name: extract 18 | args: 19 | code: | 20 | () => '\n' + [...new Set(Array.from(document.querySelectorAll('[src], [href], [url], [action]')).map(i => i.src || i.href || i.url || i.action))].join('\r\n') + '\n' 21 | 22 | matchers: 23 | - type: word 24 | words: 25 | - "test.html" 26 | 27 | extractors: 28 | - type: kval 29 | part: extract 30 | kval: 31 | - extract -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-header-action.yaml: -------------------------------------------------------------------------------- 1 | id: headless-header-action 2 | info: 3 | name: Headless Header Action 4 | author: pdteam 5 | severity: info 6 | tags: headless 7 | 8 | headless: 9 | - steps: 10 | - action: setheader 11 | args: 12 | part: request 13 | key: Test 14 | value: test value 15 | 16 | - action: navigate 17 | args: 18 | url: "{{BaseURL}}/" 19 | 20 | - action: waitload 21 | matchers: 22 | - type: word 23 | words: 24 | - "test value" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-header-status-test.yaml: -------------------------------------------------------------------------------- 1 | id: headless-header-status-test 2 | 3 | info: 4 | name: headless header + status test 5 | author: pdteam 6 | severity: info 7 | 8 | headless: 9 | - steps: 10 | - args: 11 | url: "{{BaseURL}}" 12 | action: navigate 13 | - action: waitload 14 | 15 | matchers-condition: and 16 | matchers: 17 | - type: word 18 | part: header 19 | words: 20 | - text/plain 21 | 22 | - type: status 23 | status: 24 | - 200 25 | -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-local.yaml: -------------------------------------------------------------------------------- 1 | id: nuclei-headless-local 2 | 3 | info: 4 | name: Nuclei Headless Local 5 | author: pdteam 6 | severity: high 7 | 8 | headless: 9 | - steps: 10 | - action: navigate 11 | args: 12 | url: "{{BaseURL}}" 13 | 14 | - action: waitload 15 | -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-payloads.yaml: -------------------------------------------------------------------------------- 1 | id: headless-payloads 2 | 3 | info: 4 | name: headless payloads example 5 | author: pdteam 6 | severity: info 7 | tags: headless 8 | 9 | headless: 10 | - attack: clusterbomb 11 | payloads: 12 | aa: 13 | - aa 14 | - bb 15 | bb: 16 | - cc 17 | - dd 18 | steps: 19 | - args: 20 | url: "{{BaseURL}}?aa={{aa}}&bb={{bb}}" 21 | action: navigate 22 | - action: waitload 23 | matchers: 24 | - type: word 25 | words: 26 | - "test" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-self-contained.yaml: -------------------------------------------------------------------------------- 1 | id: headless-self-contained 2 | info: 3 | name: Headless Self Contained 4 | author: pdteam 5 | severity: info 6 | tags: headless 7 | 8 | self-contained: true 9 | 10 | headless: 11 | - steps: 12 | - action: navigate 13 | args: 14 | url: "https://postman-echo.com/get?q={{query}}" 15 | 16 | - action: waitload 17 | matchers: 18 | - type: word 19 | words: 20 | - "selfcontained" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/headless-waitevent.yaml: -------------------------------------------------------------------------------- 1 | id: headless-waitevent 2 | 3 | info: 4 | name: WaitEvent 5 | severity: info 6 | author: pdteam 7 | 8 | headless: 9 | - steps: 10 | # note waitevent must be used before navigating to any page 11 | # unlike waitload 12 | - action: waitevent 13 | args: 14 | event: 'Page.loadEventFired' 15 | max-duration: 15s 16 | 17 | - action: navigate 18 | args: 19 | url: "{{BaseURL}}/" 20 | 21 | matchers: 22 | - type: word 23 | words: 24 | - "" -------------------------------------------------------------------------------- /integration_tests/protocols/headless/variables.yaml: -------------------------------------------------------------------------------- 1 | id: variables-example 2 | 3 | info: 4 | name: Variables Example 5 | author: pdteam 6 | severity: info 7 | 8 | variables: 9 | a1: "{{base64('hello')}}" 10 | 11 | headless: 12 | - steps: 13 | - args: 14 | url: "{{BaseURL}}" 15 | action: navigate 16 | - action: waitload 17 | matchers: 18 | - type: word 19 | words: 20 | - "{{a1}}" -------------------------------------------------------------------------------- /integration_tests/protocols/http/annotation-timeout.yaml: -------------------------------------------------------------------------------- 1 | id: annotation-timeout 2 | 3 | info: 4 | name: Basic Annotation Timeout 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | @timeout: 5s 12 | GET / HTTP/1.1 13 | Host: {{Hostname}} 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - "This is test matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/cl-body-with-header.yaml: -------------------------------------------------------------------------------- 1 | id: cl-body-with-header 2 | 3 | info: 4 | name: CL Get Request - Body with header 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: dsl 14 | dsl: 15 | - "content_length==50000 && len(body)==14" -------------------------------------------------------------------------------- /integration_tests/protocols/http/cl-body-without-header.yaml: -------------------------------------------------------------------------------- 1 | id: cl-body-without-header 2 | 3 | info: 4 | name: CL Get Request - Body without header 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: dsl 14 | dsl: 15 | - "content_length==14" -------------------------------------------------------------------------------- /integration_tests/protocols/http/cli-with-constants.yaml: -------------------------------------------------------------------------------- 1 | id: cli-with-constants 2 | 3 | info: 4 | name: Cli Var with Constants 5 | author: pdteam 6 | severity: info 7 | 8 | constants: 9 | test: test-in-template 10 | 11 | http: 12 | - method: GET 13 | path: 14 | - "{{BaseURL}}?p={{test}}" 15 | matchers: 16 | - type: word 17 | words: 18 | - "test-in-template" -------------------------------------------------------------------------------- /integration_tests/protocols/http/custom-attack-type.yaml: -------------------------------------------------------------------------------- 1 | id: custom-attack-type 2 | 3 | info: 4 | name: Custom Attack Type 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}/?a={{test}}&b={{values}}" 12 | payloads: 13 | test: 14 | - hello 15 | - another 16 | values: 17 | - data 18 | - hacking 19 | attack: pitchfork 20 | matchers: 21 | - type: word 22 | words: 23 | - "This is test custom payload" 24 | -------------------------------------------------------------------------------- /integration_tests/protocols/http/default-matcher-condition.yaml: -------------------------------------------------------------------------------- 1 | id: default-matcher-condition 2 | 3 | info: 4 | name: default-matcher-condition 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET /?action=curltest&url={{interactsh-url}} HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | matchers: 15 | - type: word 16 | part: interactsh_protocol 17 | words: 18 | - "dns" 19 | 20 | - type: status 21 | status: 22 | - 200 23 | -------------------------------------------------------------------------------- /integration_tests/protocols/http/disable-path-automerge.yaml: -------------------------------------------------------------------------------- 1 | id: test 2 | 3 | info: 4 | name: test 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET /api/v1/test?id=123 HTTP/1.1 12 | Host: {{Hostname}} 13 | - | 14 | GET HTTP/1.1 15 | Host: {{Hostname}} 16 | disable-path-automerge: true 17 | matchers: 18 | - type: status 19 | status: 20 | - 200 21 | -------------------------------------------------------------------------------- /integration_tests/protocols/http/disable-redirects.yaml: -------------------------------------------------------------------------------- 1 | id: basic-disable-redirects 2 | 3 | info: 4 | name: Basic GET Redirects Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | redirects: true 13 | max-redirects: 2 14 | matchers: 15 | - type: word 16 | words: 17 | - "This is test disable redirects matcher text" 18 | -------------------------------------------------------------------------------- /integration_tests/protocols/http/dsl-matcher-variable.yaml: -------------------------------------------------------------------------------- 1 | id: dsl-matcher-variable 2 | 3 | info: 4 | name: dsl-matcher-variable 5 | author: pd-team 6 | severity: info 7 | 8 | http: 9 | - 10 | path: 11 | - "{{BaseURL}}" 12 | payloads: 13 | VALUES: 14 | - This 15 | - is 16 | - test 17 | - matcher 18 | - text 19 | matchers: 20 | - 21 | dsl: 22 | - 'contains(body,"{{VALUES}}")' 23 | type: dsl -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-all-ips.yaml: -------------------------------------------------------------------------------- 1 | id: get-all-ips 2 | 3 | info: 4 | name: Basic GET Request on all IPS 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "ok" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-case-insensitive.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-case-insensitive 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | case-insensitive: true 15 | words: 16 | - "ThIS is TEsT MAtcHEr TExT" 17 | -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-headers.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-headers 2 | 3 | info: 4 | name: Basic GET Headers Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | headers: 13 | test: nuclei 14 | matchers: 15 | - type: word 16 | words: 17 | - "This is test headers matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-host-redirects.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-host-redirects 2 | 3 | info: 4 | name: Basic GET Host Redirects Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | host-redirects: true 13 | max-redirects: 3 14 | matchers: 15 | - type: dsl 16 | dsl: 17 | - "status_code==307" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-override-sni.yaml: -------------------------------------------------------------------------------- 1 | id: basic-raw-http-example 2 | 3 | info: 4 | name: Test RAW GET Template 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | @tls-sni:request.host 12 | GET / HTTP/1.1 13 | Host: test 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - "test-ok" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-query-string.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-querystring 2 | 3 | info: 4 | name: Basic GET QueryString Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}?test=nuclei" 12 | matchers: 13 | - type: word 14 | words: 15 | - "This is test querystring matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-redirects-chain-headers.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-redirects-chain-headers 2 | 3 | info: 4 | name: Basic GET Redirects Request With Chain header 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | redirects: true 13 | max-redirects: 3 14 | matchers-condition: and 15 | matchers: 16 | - type: word 17 | part: header 18 | words: 19 | - "TestRedirectHeaderMatch" 20 | 21 | - type: status 22 | status: 23 | - 302 -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-redirects.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-redirects 2 | 3 | info: 4 | name: Basic GET Redirects Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | redirects: true 13 | max-redirects: 3 14 | matchers: 15 | - type: word 16 | words: 17 | - "This is test redirects matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-sni-unsafe.yaml: -------------------------------------------------------------------------------- 1 | id: basic-unsafe-get 2 | 3 | info: 4 | name: Basic Unsafe GET Request with CLI SNI 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - |+ 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | unsafe: true 15 | matchers: 16 | - type: word 17 | words: 18 | - "test-ok" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-sni.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-sni 2 | 3 | info: 4 | name: Basic GET Request with CLI SNI 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "test-ok" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get-without-scheme.yaml: -------------------------------------------------------------------------------- 1 | id: get-without-scheme 2 | 3 | info: 4 | name: Basic GET Request without scheme 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "ok" -------------------------------------------------------------------------------- /integration_tests/protocols/http/get.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "This is test matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/http-preprocessor.yaml: -------------------------------------------------------------------------------- 1 | id: http-preprocessor 2 | 3 | info: 4 | name: Test Http Preprocessor 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET /?test={{randstr}} HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | matchers: 15 | - type: status 16 | status: 17 | - 200 -------------------------------------------------------------------------------- /integration_tests/protocols/http/interactsh-requests-mc-and.yaml: -------------------------------------------------------------------------------- 1 | id: interactsh-requests-mc-and 2 | 3 | info: 4 | name: interactsh multi request matcher condition 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET /api/geoping/{{interactsh-url}} HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | - | 15 | GET / HTTP/1.1 16 | Host: {{Hostname}} 17 | 18 | matchers-condition: and 19 | matchers: 20 | - type: word 21 | part: interactsh_protocol # Confirms the DNS Interaction 22 | words: 23 | - "dns" 24 | 25 | - type: dsl 26 | dsl: 27 | - "status_code_2 == 200" -------------------------------------------------------------------------------- /integration_tests/protocols/http/interactsh-stop-at-first-match.yaml: -------------------------------------------------------------------------------- 1 | id: interactsh-stop-at-first-match-integration-test 2 | 3 | info: 4 | name: Interactsh StopAtFirstMatch Integration Test 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}/?a=1" 12 | - "{{BaseURL}}/?a=2" 13 | - "{{BaseURL}}/?a=3" 14 | - "{{BaseURL}}/?a=4" 15 | - "{{BaseURL}}/?a=5" 16 | - "{{BaseURL}}/?a=6" 17 | - "{{BaseURL}}/?a=7" 18 | - "{{BaseURL}}/?a=8" 19 | - "{{BaseURL}}/?a=9" 20 | headers: 21 | url: 'http://{{interactsh-url}}' 22 | 23 | stop-at-first-match: true 24 | 25 | matchers: 26 | - type: word 27 | part: interactsh_protocol # Confirms DNS Interaction 28 | words: 29 | - "dns" -------------------------------------------------------------------------------- /integration_tests/protocols/http/interactsh.yaml: -------------------------------------------------------------------------------- 1 | id: interactsh-integration-test 2 | 3 | info: 4 | name: Interactsh Integration Test 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | headers: 13 | url: 'http://{{interactsh-url}}' 14 | 15 | matchers: 16 | - type: word 17 | part: interactsh_protocol # Confirms the HTTP Interaction 18 | words: 19 | - "dns" -------------------------------------------------------------------------------- /integration_tests/protocols/http/multi-http-var-sharing.yaml: -------------------------------------------------------------------------------- 1 | id: multi-http-var-sharing 2 | 3 | info: 4 | name: Multi HTTP var sharing 5 | author: pdteam 6 | severity: info 7 | description: | 8 | A template which has multiple HTTP requests block and variables are shared between them 9 | 10 | http: 11 | - method: GET 12 | path: 13 | - "{{BaseURL}}" 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - "This is test matcher text" 19 | negative: true 20 | internal: true 21 | 22 | extractors: 23 | - type: dsl 24 | name: ffff 25 | dsl: 26 | - status_code 27 | internal: true 28 | 29 | - method: GET 30 | path: 31 | - "{{BaseURL}}/{{ffff}}" 32 | 33 | matchers: 34 | - type: status 35 | status: 36 | - 200 -------------------------------------------------------------------------------- /integration_tests/protocols/http/multi-request.yaml: -------------------------------------------------------------------------------- 1 | id: http-multi-request 2 | 3 | info: 4 | name: http multi request template 5 | author: pdteam 6 | severity: info 7 | description: template with multiple http request with combined logic 8 | reference: https://example-reference-link 9 | 10 | # requestURI is reflected back as response body here 11 | http: 12 | - raw: 13 | - | 14 | GET /ping HTTP/1.1 15 | Host: {{Hostname}} 16 | 17 | - | 18 | GET /pong HTTP/1.1 19 | Host: {{Hostname}} 20 | 21 | matchers: 22 | - type: dsl 23 | dsl: 24 | - 'body_1 == "ping"' 25 | - 'body_2 == "pong"' 26 | condition: and -------------------------------------------------------------------------------- /integration_tests/protocols/http/post-body.yaml: -------------------------------------------------------------------------------- 1 | id: basic-post-body 2 | 3 | info: 4 | name: Basic POST Body Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: POST 10 | path: 11 | - "{{BaseURL}}" 12 | headers: 13 | Content-Type: application/x-www-form-urlencoded 14 | Content-Length: 1 # as long as there is a value, nuclei will auto-recalculate it. 15 | body: username=test&password=nuclei 16 | matchers: 17 | - type: word 18 | words: 19 | - "This is test post-body matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/post-json-body.yaml: -------------------------------------------------------------------------------- 1 | id: basic-post-json-body 2 | 3 | info: 4 | name: Basic POST JSON Body Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: POST 10 | path: 11 | - "{{BaseURL}}" 12 | headers: 13 | Content-Type: application/json 14 | Content-Length: 1 15 | body: '{"username":"test","password":"nuclei"}' 16 | matchers: 17 | - type: word 18 | words: 19 | - "This is test post-json-body matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/race-multiple.yaml: -------------------------------------------------------------------------------- 1 | id: race-condition-testing 2 | 3 | info: 4 | name: Race condition testing with multiple requests 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | id=1 15 | 16 | - | 17 | GET / HTTP/1.1 18 | Host: {{Hostname}} 19 | 20 | id=2 21 | 22 | - | 23 | GET / HTTP/1.1 24 | Host: {{Hostname}} 25 | 26 | id=3 27 | 28 | - | 29 | GET / HTTP/1.1 30 | Host: {{Hostname}} 31 | 32 | id=4 33 | 34 | - | 35 | GET / HTTP/1.1 36 | Host: {{Hostname}} 37 | 38 | id=5 39 | 40 | threads: 5 41 | race: true 42 | 43 | matchers: 44 | - type: status 45 | status: 46 | - 200 -------------------------------------------------------------------------------- /integration_tests/protocols/http/race-simple.yaml: -------------------------------------------------------------------------------- 1 | id: race-condition-testing 2 | 3 | info: 4 | name: Race Condition testing 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | test 15 | 16 | race: true 17 | race_count: 10 18 | 19 | matchers: 20 | - type: status 21 | part: header 22 | status: 23 | - 200 -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-get-query.yaml: -------------------------------------------------------------------------------- 1 | id: basic-raw-query-example 2 | 3 | info: 4 | name: Test RAW GET Query Template 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET ?test=nuclei HTTP/1.1 12 | Host: {{Hostname}} 13 | Origin: {{BaseURL}} 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - "Test is test raw-get-query-matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-get.yaml: -------------------------------------------------------------------------------- 1 | id: basic-raw-http-example 2 | 3 | info: 4 | name: Test RAW GET Template 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | Origin: {{BaseURL}} 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - "Test is test raw-get-matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-path-single-slash.yaml: -------------------------------------------------------------------------------- 1 | id: raw-path-single-slash 2 | 3 | info: 4 | name: Test RAW HTTP Template with single slash 5 | author: pdteam 6 | severity: info 7 | 8 | requests: 9 | - raw: 10 | - | 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | Origin: {{BaseURL}} -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-path-trailing-slash.yaml: -------------------------------------------------------------------------------- 1 | id: raw-path-trailing-slash 2 | 3 | info: 4 | name: Test RAW HTTP Template with trailing slash 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET /test/..;/..;/ HTTP/1.1 12 | Host: {{Hostname}} 13 | Origin: {{BaseURL}} -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-payload.yaml: -------------------------------------------------------------------------------- 1 | id: payload-raw-example 2 | info: 3 | name: Test RAW With Payload Template 4 | author: pdteam 5 | severity: info 6 | 7 | http: 8 | - payloads: 9 | username: 10 | - test 11 | password: 12 | - nuclei 13 | - guest 14 | attack: clusterbomb 15 | raw: 16 | - | 17 | POST / HTTP/1.1 18 | User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) 19 | Host: {{Hostname}} 20 | Content-Type: application/x-www-form-urlencoded 21 | Content-Length: 1 22 | another_header: {{base64('§password§')}} 23 | Accept: */* 24 | 25 | username=§username§&password={{password}} 26 | matchers: 27 | - type: word 28 | words: 29 | - "Test is raw-payload matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-post-body.yaml: -------------------------------------------------------------------------------- 1 | id: basic-raw-http-body-example 2 | 3 | info: 4 | name: Test RAW POST Template 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | POST / HTTP/1.1 12 | Host: {{Hostname}} 13 | Origin: {{BaseURL}} 14 | Content-Type: application/x-www-form-urlencoded 15 | Content-Length: 1 16 | 17 | username=test&password=nuclei 18 | matchers: 19 | - type: word 20 | words: 21 | - "Test is test raw-post-body-matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-unsafe-path-single-slash.yaml: -------------------------------------------------------------------------------- 1 | id: raw-unsafe-path-single-slash 2 | 3 | info: 4 | name: Test RAW Unsafe HTTP Template with single slash 5 | author: pdteam 6 | severity: info 7 | 8 | requests: 9 | - raw: 10 | - |+ 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | Origin: {{BaseURL}} 14 | 15 | unsafe: true -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-unsafe-request.yaml: -------------------------------------------------------------------------------- 1 | id: basic-raw-unsafe-request-example 2 | 3 | info: 4 | name: Test RAW Unsafe Request Template 5 | author: pd-team 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - |+ 11 | GET / HTTP/1.1 12 | Host: 13 | Content-Length: 4 14 | 15 | unsafe: true 16 | matchers-condition: and 17 | matchers: 18 | - type: word 19 | words: 20 | - "This is test raw-unsafe-matcher test" -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-unsafe-with-params.yaml: -------------------------------------------------------------------------------- 1 | id: raw-unsafe-with-params 2 | 3 | info: 4 | name: Test RAW unsafe with params 5 | author: pdteam 6 | severity: info 7 | # this test is used to check automerge of params in both unsafe & safe requests 8 | # key1=value1 is added from inputURL 9 | 10 | http: 11 | - raw: 12 | - |+ 13 | GET /?key2=value2 HTTP/1.1 14 | Host: {{Hostname}} 15 | 16 | unsafe: true 17 | matchers: 18 | - type: word 19 | words: 20 | - "Test is test raw-params-matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/raw-with-params.yaml: -------------------------------------------------------------------------------- 1 | id: raw-with-params 2 | 3 | info: 4 | name: Test RAW Params Template 5 | author: pdteam 6 | severity: info 7 | # this test is used to check automerge of params in both unsafe & safe requests 8 | # key1=value1 is added from inputURL 9 | 10 | http: 11 | - raw: 12 | - | 13 | GET /?key2=value2 HTTP/1.1 14 | Host: {{Hostname}} 15 | Origin: {{BaseURL}} 16 | 17 | matchers: 18 | - type: word 19 | words: 20 | - "Test is test raw-params-matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/redirect-match-url.yaml: -------------------------------------------------------------------------------- 1 | id: redirect-match-url 2 | 3 | info: 4 | name: Redirect Match URL 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | stop-at-first-match: true # Confirm stop-at-first-match 13 | redirects: true # Confirm redirected URL matched value 14 | max-redirects: 3 15 | matchers: 16 | - type: word 17 | words: 18 | - "This is test redirects matcher text" -------------------------------------------------------------------------------- /integration_tests/protocols/http/request-condition-new.yaml: -------------------------------------------------------------------------------- 1 | id: request-condition-new 2 | 3 | info: 4 | name: request-condition-new 5 | author: pd-team 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | id: first 11 | path: 12 | - "{{BaseURL}}/200" 13 | - method: GET 14 | path: 15 | - "{{BaseURL}}/400" 16 | matchers: 17 | - type: dsl 18 | dsl: 19 | - "first_status_code==200 && status_code==400" -------------------------------------------------------------------------------- /integration_tests/protocols/http/request-condition.yaml: -------------------------------------------------------------------------------- 1 | id: request-condition 2 | 3 | info: 4 | name: request-condition 5 | author: pd-team 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}/200" 12 | - "{{BaseURL}}/400" 13 | 14 | matchers: 15 | - type: dsl 16 | dsl: 17 | - "status_code_1==200 && status_code_2==400" -------------------------------------------------------------------------------- /integration_tests/protocols/http/self-contained-file-input.yaml: -------------------------------------------------------------------------------- 1 | id: self-contained-file-input 2 | 3 | info: 4 | name: Test Self Contained Template With File Input 5 | author: pdteam 6 | severity: info 7 | 8 | self-contained: true 9 | http: 10 | - method: GET 11 | path: 12 | - "http://127.0.0.1:5431/{{test}}" 13 | matchers: 14 | - type: word 15 | words: 16 | - This is self-contained response 17 | 18 | - raw: 19 | - | 20 | GET http://127.0.0.1:5431/{{test}} HTTP/1.1 21 | Host: {{Hostname}} 22 | matchers: 23 | - type: word 24 | words: 25 | - This is self-contained response -------------------------------------------------------------------------------- /integration_tests/protocols/http/self-contained-with-params.yaml: -------------------------------------------------------------------------------- 1 | id: self-contained-with-params 2 | 3 | info: 4 | name: self contained with params 5 | author: pd-team 6 | severity: info 7 | 8 | self-contained: true 9 | http: 10 | - raw: 11 | - | 12 | GET http://127.0.0.1:5431/?something=here&key=value HTTP/1.1 13 | Host: {{Hostname}} 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - This is self-contained response -------------------------------------------------------------------------------- /integration_tests/protocols/http/self-contained-with-path.yaml: -------------------------------------------------------------------------------- 1 | id: self-contained-with-path 2 | 3 | info: 4 | name: self-contained-with-path 5 | author: pd-team 6 | severity: info 7 | 8 | self-contained: true 9 | http: 10 | - raw: 11 | - | 12 | GET / HTTP/1.1 13 | Host: 127.0.0.1:5431 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - This is self-contained response -------------------------------------------------------------------------------- /integration_tests/protocols/http/self-contained.yaml: -------------------------------------------------------------------------------- 1 | id: example-self-contained-input 2 | 3 | info: 4 | name: example-self-contained 5 | author: pd-team 6 | severity: info 7 | 8 | self-contained: true 9 | http: 10 | - raw: 11 | - | 12 | GET http://127.0.0.1:5431/ HTTP/1.1 13 | Host: {{Hostname}} 14 | 15 | matchers: 16 | - type: word 17 | words: 18 | - This is self-contained response -------------------------------------------------------------------------------- /integration_tests/protocols/http/stop-at-first-match-with-extractors.yaml: -------------------------------------------------------------------------------- 1 | id: stop-at-first-match-with-extractors 2 | 3 | info: 4 | name: Stop at first match Request with extractors 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}?a=1" 12 | - "{{BaseURL}}?a=2" 13 | stop-at-first-match: true 14 | extractors: 15 | - type: kval 16 | part: header 17 | kval: 18 | - "date" -------------------------------------------------------------------------------- /integration_tests/protocols/http/stop-at-first-match.yaml: -------------------------------------------------------------------------------- 1 | id: stop-at-first-match 2 | 3 | info: 4 | name: Stop at first match Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}?a=1" 12 | - "{{BaseURL}}?a=2" 13 | matchers: 14 | - type: word 15 | words: 16 | - "This is test" 17 | stop-at-first-match: true -------------------------------------------------------------------------------- /integration_tests/protocols/http/variable-dsl-function.yaml: -------------------------------------------------------------------------------- 1 | id: basic-example 2 | 3 | info: 4 | name: Test HTTP Template 5 | author: pdteam 6 | severity: info 7 | 8 | variables: 9 | a1: "{{to_lower(rand_base(5))}}" 10 | 11 | 12 | http: 13 | - method: GET 14 | path: 15 | - "{{BaseURL}}/?x={{a1}}" 16 | - "{{BaseURL}}/?x={{a1}}" 17 | 18 | extractors: 19 | - type: dsl 20 | dsl: 21 | - a1 -------------------------------------------------------------------------------- /integration_tests/protocols/http/variables.yaml: -------------------------------------------------------------------------------- 1 | id: variables-example 2 | 3 | info: 4 | name: Variables Example 5 | author: pdteam 6 | severity: info 7 | 8 | variables: 9 | a1: "value" 10 | a2: "{{base64('{{Host}}')}}" 11 | 12 | http: 13 | - raw: 14 | - | 15 | GET / HTTP/1.1 16 | Host: {{FQDN}} 17 | Test: {{a1}} 18 | Another: {{a2}} 19 | Email: {{ username }} 20 | payloads: 21 | username: 22 | - jon.doe@{{ FQDN }} 23 | stop-at-first-match: true 24 | matchers-condition: or 25 | matchers: 26 | - type: word 27 | condition: and 28 | words: 29 | - "value" 30 | - "MTI3LjAuMC4x" # 127.0.0.1 31 | - "jon.doe@127.0.0.1" 32 | -------------------------------------------------------------------------------- /integration_tests/protocols/javascript/net-https.yaml: -------------------------------------------------------------------------------- 1 | id: net-https 2 | 3 | info: 4 | name: net-https 5 | author: pdteam 6 | severity: info 7 | description: send and receive https data using net module 8 | 9 | 10 | javascript: 11 | - code: | 12 | let m = require('nuclei/net'); 13 | let name=Host+':'+Port; 14 | let conn = m.OpenTLS('tcp', name); 15 | conn.Send('GET / HTTP/1.1\r\nHost:'+name+'\r\nConnection: close\r\n\r\n'); 16 | resp = conn.RecvString(); 17 | 18 | args: 19 | Host: "{{Host}}" 20 | Port: "443" 21 | 22 | matchers: 23 | - type: word 24 | words: 25 | - "HTTP/1.1 200 OK" -------------------------------------------------------------------------------- /integration_tests/protocols/javascript/ssh-server-fingerprint.yaml: -------------------------------------------------------------------------------- 1 | id: ssh-server-fingerprint 2 | 3 | info: 4 | name: Fingerprint SSH Server Software 5 | author: Ice3man543,tarunKoyalwar 6 | severity: info 7 | metadata: 8 | shodan-query: port:22 9 | 10 | 11 | javascript: 12 | - code: | 13 | var m = require("nuclei/ssh"); 14 | var c = m.SSHClient(); 15 | var response = c.ConnectSSHInfoMode(Host, Port); 16 | to_json(response); 17 | args: 18 | Host: "{{Host}}" 19 | Port: "22" 20 | 21 | extractors: 22 | - type: json 23 | name: server 24 | json: 25 | - '.ServerID.Raw' 26 | part: response 27 | -------------------------------------------------------------------------------- /integration_tests/protocols/keys/README.md: -------------------------------------------------------------------------------- 1 | ## keys 2 | 3 | the keys stored here especially `ci-private-key.pem` and `ci.crt` are used in integration tests to test template signing and verfication functionality introduced in nuclei v3 -------------------------------------------------------------------------------- /integration_tests/protocols/keys/ci-private-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PD NUCLEI USER PRIVATE KEY----- 2 | MHcCAQEEIEywlBGZ94ARrBT+1fTu/Ii7HGfJc4y7kK4aGYvDMYm5oAoGCCqGSM49 3 | AwEHoUQDQgAEnyVUkFKJx92/8doQ//VAPCrzB4dqvNgwLRZPC/oAieVpNG8HDGNw 4 | PJ7qB7ovIfGwDOW98vQwsRG4TmgFlZr0rQ== 5 | -----END PD NUCLEI USER PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /integration_tests/protocols/keys/ci.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN PD NUCLEI USER CERTIFICATE----- 2 | MIIBPzCB56ADAgECAgRlHGgmMAoGCCqGSM49BAMCMA0xCzAJBgNVBAMTAkNJMB4X 3 | DTIzMTAwMzE5MTQ0NloXDTI3MTAwMjE5MTQ0NlowDTELMAkGA1UEAxMCQ0kwWTAT 4 | BgcqhkjOPQIBBggqhkjOPQMBBwNCAASfJVSQUonH3b/x2hD/9UA8KvMHh2q82DAt 5 | Fk8L+gCJ5Wk0bwcMY3A8nuoHui8h8bAM5b3y9DCxEbhOaAWVmvStozUwMzAOBgNV 6 | HQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAK 7 | BggqhkjOPQQDAgNHADBEAiBgUdbAcSbDpkNNQscZog/pAuaRV4sk7fbOlTRcjZTL 8 | qQIgdtvG1w7l9VAtk6gx+HJa3BP9IFhSfT+a3UCuJy2p2iA= 9 | -----END PD NUCLEI USER CERTIFICATE----- 10 | -------------------------------------------------------------------------------- /integration_tests/protocols/multi/dynamic-values.yaml: -------------------------------------------------------------------------------- 1 | id: dns-http-dynamic-values 2 | 3 | info: 4 | name: multi protocol request with dynamic values 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" # DNS Request 10 | type: cname 11 | 12 | extractors: 13 | - type: dsl 14 | name: blogid 15 | dsl: 16 | - trim_suffix(cname,'.vercel-dns.com') 17 | internal: true 18 | 19 | http: 20 | - method: GET # http request 21 | path: 22 | - "{{BaseURL}}" 23 | 24 | matchers: 25 | - type: dsl 26 | dsl: 27 | - contains(body,'home') # check for http string 28 | - blogid == 'cname' # check for cname (extracted information from dns response) 29 | condition: and -------------------------------------------------------------------------------- /integration_tests/protocols/multi/evaluate-variables.yaml: -------------------------------------------------------------------------------- 1 | id: dns-ssl-http-with-variables 2 | 3 | info: 4 | name: multi protocol request with dynamic values 5 | author: pdteam 6 | severity: info 7 | 8 | 9 | variables: 10 | cname_filtered: '{{trim_suffix(dns_cname,".vercel-dns.com")}}' 11 | 12 | dns: 13 | - name: "{{FQDN}}" # DNS Request 14 | type: cname 15 | 16 | ssl: 17 | - address: "{{Hostname}}" # ssl request 18 | 19 | http: 20 | - method: GET # http request 21 | path: 22 | - "{{BaseURL}}" 23 | 24 | matchers: 25 | - type: dsl 26 | dsl: 27 | - contains(http_body,'home') # check for http string 28 | - cname_filtered == 'cname' # check for cname (extracted information from dns response) 29 | - ssl_subject_cn == 'docs.projectdiscovery.io' 30 | condition: and -------------------------------------------------------------------------------- /integration_tests/protocols/multi/exported-response-vars.yaml: -------------------------------------------------------------------------------- 1 | id: dns-ssl-http-proto-prefix 2 | 3 | info: 4 | name: multi protocol request with dynamic values 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" # DNS Request 10 | type: cname 11 | 12 | ssl: 13 | - address: "{{Hostname}}" # ssl request 14 | 15 | http: 16 | - method: GET # http request 17 | path: 18 | - "{{BaseURL}}" 19 | 20 | matchers: 21 | - type: dsl 22 | dsl: 23 | - contains(http_body,'home') # check for http string 24 | - trim_suffix(dns_cname,'.vercel-dns.com') == 'cname' # check for cname (extracted information from dns response) 25 | - ssl_subject_cn == 'docs.projectdiscovery.io' 26 | condition: and -------------------------------------------------------------------------------- /integration_tests/protocols/network/basic.yaml: -------------------------------------------------------------------------------- 1 | id: basic-network-request 2 | 3 | info: 4 | name: Basic Network Request 5 | author: pdteam 6 | severity: info 7 | 8 | network: 9 | - host: 10 | - "{{Hostname}}" 11 | inputs: 12 | - data: "PING\r\n" 13 | read-size: 4 14 | matchers: 15 | - type: word 16 | part: data 17 | words: 18 | - "PONG" -------------------------------------------------------------------------------- /integration_tests/protocols/network/hex.yaml: -------------------------------------------------------------------------------- 1 | id: hex-network-request 2 | 3 | info: 4 | name: Hex Input Network Request 5 | author: pdteam 6 | severity: info 7 | 8 | network: 9 | - host: 10 | - "{{Hostname}}" 11 | inputs: 12 | - data: "50494e47" 13 | type: hex 14 | - data: "\r\n" 15 | 16 | read-size: 4 17 | matchers: 18 | - type: word 19 | part: data 20 | encoding: hex 21 | words: 22 | - "504f4e47" -------------------------------------------------------------------------------- /integration_tests/protocols/network/multi-step.yaml: -------------------------------------------------------------------------------- 1 | id: multi-step 2 | 3 | info: 4 | name: Multi-Step Network Template 5 | author: pd-team 6 | severity: info 7 | 8 | network: 9 | - inputs: 10 | - data: "FIRST" 11 | read: 4 12 | name: first 13 | - data: "SECOND" 14 | read: 4 15 | name: second 16 | host: 17 | - "{{Hostname}}" 18 | read-size: 6 19 | matchers: 20 | - type: word 21 | part: first 22 | words: 23 | - "PING" 24 | - type: word 25 | part: second 26 | words: 27 | - "PONG" 28 | - type: word 29 | part: data 30 | words: 31 | - "NUCLEI" 32 | matchers-condition: and -------------------------------------------------------------------------------- /integration_tests/protocols/network/net-https.yaml: -------------------------------------------------------------------------------- 1 | id: net-https 2 | 3 | info: 4 | name: Example Network template to send HTTPS request 5 | author: pdteam 6 | severity: high 7 | description: Example Network template to send HTTPS request 8 | 9 | 10 | tcp: 11 | - host: 12 | - "tls://{{Hostname}}" 13 | port: 443 14 | inputs: 15 | - data: "GET / HTTP/1.1\r\nHost: {{Hostname}}\r\nConnection: close\r\n\r\n" 16 | read-all: true 17 | extractors: 18 | - type: dsl 19 | dsl: 20 | - "len(data)" -------------------------------------------------------------------------------- /integration_tests/protocols/network/network-port.yaml: -------------------------------------------------------------------------------- 1 | id: network-port-example 2 | 3 | info: 4 | name: Example Template with Network Port 5 | author: pdteam 6 | severity: high 7 | description: This is an updated description for the network port example. 8 | reference: https://updated-reference-link 9 | 10 | tcp: 11 | - host: 12 | - "{{Hostname}}" 13 | port: 23846 14 | inputs: 15 | - data: "PING\r\n" 16 | read-size: 4 17 | matchers: 18 | - type: word 19 | part: data 20 | words: 21 | - "PONG" 22 | -------------------------------------------------------------------------------- /integration_tests/protocols/network/same-address.yaml: -------------------------------------------------------------------------------- 1 | id: same-target 2 | 3 | info: 4 | name: same-target 5 | author: pdteam 6 | severity: info 7 | description: Riak is a distributed NoSQL key-value data store that offers high availability, fault tolerance, operational simplicity, and scalability. 8 | 9 | network: 10 | - host: 11 | - "{{Hostname}}" 12 | - "{{Hostname}}" 13 | - "{{Hostname}}" 14 | - "{{Hostname}}" 15 | - "{{Hostname}}" 16 | - "{{Hostname}}" 17 | - "{{Hostname}}" 18 | - "{{Hostname}}" 19 | - "{{Hostname}}" 20 | - "{{Hostname}}" 21 | - "{{Hostname}}" 22 | inputs: 23 | - data: "PING\r\n" 24 | read-size: 4 25 | matchers: 26 | - type: word 27 | part: data 28 | words: 29 | - "PONG" 30 | -------------------------------------------------------------------------------- /integration_tests/protocols/network/self-contained.yaml: -------------------------------------------------------------------------------- 1 | id: example-self-contained-input 2 | 3 | info: 4 | name: example-self-contained 5 | author: pd-team 6 | severity: info 7 | 8 | self-contained: true 9 | network: 10 | - host: 11 | - "127.0.0.1:5431" 12 | 13 | matchers: 14 | - type: word 15 | words: 16 | - "Authentication successful" -------------------------------------------------------------------------------- /integration_tests/protocols/network/variables.yaml: -------------------------------------------------------------------------------- 1 | id: variables-example 2 | 3 | info: 4 | name: Variables Example 5 | author: pdteam 6 | severity: info 7 | 8 | variables: 9 | a1: "PING" 10 | a2: "{{base64('hello')}}" 11 | 12 | network: 13 | - host: 14 | - "{{Hostname}}" 15 | inputs: 16 | - data: "{{a1}}" 17 | read-size: 8 18 | matchers: 19 | - type: word 20 | part: data 21 | words: 22 | - "{{a2}}" -------------------------------------------------------------------------------- /integration_tests/protocols/offlinehttp/data/req-resp-with-http-keywords.txt: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host: pastebin.com 3 | User-Agent: curl/7.79.1 4 | Accept: */* 5 | Connection: close 6 | 7 | HTTP/1.1 200 OK 8 | Date: Tue, 21 Jun 2022 09:32:01 GMT 9 | Content-Type: text/plain; charset=utf-8 10 | Connection: close 11 | x-frame-options: DENY 12 | x-content-type-options: nosniff 13 | x-xss-protection: 1;mode=block 14 | cache-control: public, max-age=1801 15 | CF-Cache-Status: HIT 16 | Age: 1585 17 | Last-Modified: Tue, 21 Jun 2022 09:05:36 GMT 18 | Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" 19 | Server: cloudflare 20 | CF-RAY: 71ebbc0a7ea83b8b-CDG 21 | 22 | 54 23 | line1 24 | this is a line containing HTTP/1.1 FOO BAR 25 | line3 26 | 0 -------------------------------------------------------------------------------- /integration_tests/protocols/offlinehttp/offline-allowed-paths.yaml: -------------------------------------------------------------------------------- 1 | id: offline-allowed-paths 2 | 3 | info: 4 | name: offline-allowed-paths 5 | author: pdteam 6 | severity: info 7 | description: offline-allowed-paths 8 | 9 | http: 10 | - path: 11 | - "{{BaseURL}}" 12 | - "{{BaseURL}}/" 13 | - "/" 14 | 15 | matchers: 16 | - type: status 17 | status: 18 | - 200 -------------------------------------------------------------------------------- /integration_tests/protocols/offlinehttp/offline-raw.yaml: -------------------------------------------------------------------------------- 1 | id: offline-raw 2 | info: 3 | name: Test Offline raw Template 4 | author: pdteam 5 | severity: info 6 | 7 | http: 8 | - raw: 9 | - | 10 | GET / HTTP/1.1 11 | Host: {{Hostname}} 12 | 13 | matchers: 14 | - type: status 15 | status: 16 | - 200 -------------------------------------------------------------------------------- /integration_tests/protocols/offlinehttp/rfc-req-resp.yaml: -------------------------------------------------------------------------------- 1 | id: rfc-req-resp 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "this is a line containing HTTP/1.1 FOO BAR" -------------------------------------------------------------------------------- /integration_tests/protocols/ssl/basic-ztls.yaml: -------------------------------------------------------------------------------- 1 | id: basic-ssl-tls 2 | 3 | info: 4 | name: Basic SSL Request with ztls 5 | author: pdteam 6 | severity: info 7 | 8 | ssl: 9 | - address: "{{Host}}:{{Port}}" 10 | 11 | min_version: ssl30 12 | max_version: tls12 13 | 14 | matchers: 15 | - type: dsl 16 | dsl: 17 | - "tls_connection == 'ztls'" 18 | -------------------------------------------------------------------------------- /integration_tests/protocols/ssl/basic.yaml: -------------------------------------------------------------------------------- 1 | id: basic-ssl 2 | 3 | info: 4 | name: Basic SSL Request 5 | author: pdteam 6 | severity: info 7 | 8 | ssl: 9 | - address: "{{Host}}:{{Port}}" 10 | 11 | matchers: 12 | - type: dsl 13 | dsl: 14 | - "probe_status == true" 15 | -------------------------------------------------------------------------------- /integration_tests/protocols/ssl/custom-cipher.yaml: -------------------------------------------------------------------------------- 1 | id: custom-cipher 2 | 3 | info: 4 | name: Basic SSL Request 5 | author: pdteam 6 | severity: info 7 | 8 | ssl: 9 | - address: "{{Host}}:{{Port}}" 10 | 11 | cipher_suites: 12 | - TLS_AES_128_GCM_SHA256 13 | 14 | matchers: 15 | - type: word 16 | part: response 17 | words: 18 | - "TLS_AES_128_GCM_SHA256" 19 | -------------------------------------------------------------------------------- /integration_tests/protocols/ssl/custom-version.yaml: -------------------------------------------------------------------------------- 1 | id: custom-version 2 | 3 | info: 4 | name: Basic SSL Request 5 | author: pdteam 6 | severity: info 7 | 8 | ssl: 9 | - address: "{{Host}}:{{Port}}" 10 | 11 | min_version: tls12 12 | max_version: tls12 13 | 14 | matchers: 15 | - type: word 16 | part: response 17 | words: 18 | - 'tls12' 19 | -------------------------------------------------------------------------------- /integration_tests/protocols/ssl/multi-req.yaml: -------------------------------------------------------------------------------- 1 | id: multi-req 2 | 3 | info: 4 | name: Multi-Request 5 | author: pdteam 6 | severity: info 7 | 8 | ssl: 9 | - address: "{{Host}}:{{Port}}" 10 | min_version: ssl30 11 | max_version: ssl30 12 | 13 | extractors: 14 | - type: json 15 | json: 16 | - " .tls_version" 17 | 18 | - address: "{{Host}}:{{Port}}" 19 | min_version: tls10 20 | max_version: tls10 21 | 22 | extractors: 23 | - type: json 24 | json: 25 | - " .tls_version" 26 | 27 | - address: "{{Host}}:{{Port}}" 28 | min_version: tls11 29 | max_version: tls11 30 | 31 | extractors: 32 | - type: json 33 | json: 34 | - " .tls_version" -------------------------------------------------------------------------------- /integration_tests/protocols/ssl/ssl-with-vars.yaml: -------------------------------------------------------------------------------- 1 | id: ssl-with-vars 2 | 3 | info: 4 | name: SSL with variables 5 | author: pdteam 6 | severity: info 7 | tags: ssl 8 | 9 | ssl: 10 | - address: "{{Host}}:{{Port}}" 11 | matchers: 12 | - type: dsl 13 | dsl: 14 | - "print_debug(test)" 15 | -------------------------------------------------------------------------------- /integration_tests/protocols/websocket/basic.yaml: -------------------------------------------------------------------------------- 1 | id: basic-request 2 | 3 | info: 4 | name: Basic Request 5 | author: pdteam 6 | severity: info 7 | 8 | websocket: 9 | - address: '{{Scheme}}://{{Hostname}}' 10 | inputs: 11 | - data: hello 12 | matchers: 13 | - type: word 14 | words: 15 | - world 16 | part: response -------------------------------------------------------------------------------- /integration_tests/protocols/websocket/cswsh.yaml: -------------------------------------------------------------------------------- 1 | id: basic-cswsh-request 2 | 3 | info: 4 | name: Basic cswsh Request 5 | author: pdteam 6 | severity: info 7 | 8 | websocket: 9 | - address: '{{Scheme}}://{{Hostname}}' 10 | headers: 11 | Origin: 'http://evil.com' 12 | matchers: 13 | - type: word 14 | words: 15 | - true 16 | part: success -------------------------------------------------------------------------------- /integration_tests/protocols/websocket/no-cswsh.yaml: -------------------------------------------------------------------------------- 1 | id: basic-nocswsh-request 2 | 3 | info: 4 | name: Basic Non-Vulnerable cswsh Request 5 | author: pdteam 6 | severity: info 7 | 8 | websocket: 9 | - address: '{{Scheme}}://{{Hostname}}' 10 | headers: 11 | Origin: 'http://evil.com' 12 | matchers: 13 | - type: word 14 | words: 15 | - true 16 | part: success -------------------------------------------------------------------------------- /integration_tests/protocols/websocket/path.yaml: -------------------------------------------------------------------------------- 1 | id: basic-request-path 2 | 3 | info: 4 | name: Basic Request Path 5 | author: pdteam 6 | severity: info 7 | 8 | websocket: 9 | - address: '{{Scheme}}://{{Hostname}}' 10 | inputs: 11 | - data: hello 12 | matchers: 13 | - type: word 14 | words: 15 | - world 16 | part: response -------------------------------------------------------------------------------- /integration_tests/protocols/whois/basic.yaml: -------------------------------------------------------------------------------- 1 | id: basic-whois-example 2 | 3 | info: 4 | name: test template for WHOIS 5 | author: pdteam 6 | severity: info 7 | 8 | whois: 9 | - query: "{{Host}}" 10 | extractors: 11 | - type: kval 12 | kval: 13 | - "expiration date" 14 | - "registrar" -------------------------------------------------------------------------------- /integration_tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "::group::Build nuclei" 4 | rm integration-test fuzzplayground nuclei 2>/dev/null 5 | cd ../cmd/nuclei 6 | go build -race . 7 | mv nuclei ../../integration_tests/nuclei 8 | echo "::endgroup::" 9 | 10 | echo "::group::Build nuclei integration-test" 11 | cd ../integration-test 12 | go build 13 | mv integration-test ../../integration_tests/integration-test 14 | cd ../../integration_tests 15 | echo "::endgroup::" 16 | 17 | echo "::group::Installing nuclei templates" 18 | ./nuclei -update-templates 19 | echo "::endgroup::" 20 | 21 | ./integration-test 22 | if [ $? -eq 0 ] 23 | then 24 | exit 0 25 | else 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /integration_tests/subdomains.txt: -------------------------------------------------------------------------------- 1 | one 2 | docs 3 | drive 4 | play 5 | 6 | -------------------------------------------------------------------------------- /integration_tests/workflow/basic.yaml: -------------------------------------------------------------------------------- 1 | id: workflow-example 2 | 3 | info: 4 | name: Test Workflow Template 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/match-1.yaml 10 | - template: workflow/match-2.yaml -------------------------------------------------------------------------------- /integration_tests/workflow/code-template-1.yaml: -------------------------------------------------------------------------------- 1 | id: code-template-1 2 | 3 | info: 4 | name: code-template-1 5 | author: tovask 6 | severity: info 7 | tags: code 8 | 9 | code: 10 | - engine: 11 | - py 12 | - python3 13 | - python 14 | source: | 15 | print("hello from first") 16 | extractors: 17 | - type: regex 18 | name: extracted 19 | regex: 20 | - 'hello from (.*)' 21 | group: 1 22 | # digest: 490a0046304402206b3648e8d393ac4df82c7d59b1a6ee3731c66c249dbd4d9bf31f0b7f176b37ec02203184d36373e516757c7d708b5799bc16edb1cebc0a64f3442d13ded4b33c42fb:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/workflow/code-template-2.yaml: -------------------------------------------------------------------------------- 1 | id: code-template-2 2 | 3 | info: 4 | name: code-template-2 5 | author: tovask 6 | severity: info 7 | tags: code 8 | 9 | code: 10 | - engine: 11 | - py 12 | - python3 13 | - python 14 | source: | 15 | import os 16 | print("hello from " + os.getenv("extracted")) 17 | matchers: 18 | - type: word 19 | words: 20 | - "hello from first" 21 | # digest: 490a0046304402204cbb1bdf8370e49bb930b17460fb35e15f285a3b48b165736ac0e7ba2f9bc0fb022067c134790c4a2cf646b195aa4488e2c222266436e6bda47931908a28807bdb81:4a3eb6b4988d95847d4203be25ed1d46 -------------------------------------------------------------------------------- /integration_tests/workflow/code-value-share-workflow.yaml: -------------------------------------------------------------------------------- 1 | id: code-value-sharing-workflow 2 | 3 | info: 4 | name: Code Value Sharing Workflow 5 | author: tovask 6 | severity: info 7 | tags: code 8 | 9 | workflows: 10 | - template: workflow/code-template-1.yaml 11 | subtemplates: 12 | - template: workflow/code-template-2.yaml 13 | -------------------------------------------------------------------------------- /integration_tests/workflow/complex-conditions.yaml: -------------------------------------------------------------------------------- 1 | id: complex-conditions-workflow 2 | 3 | info: 4 | name: Complex Conditions Workflow 5 | author: tovask 6 | severity: info 7 | description: Workflow to test a complex scenario, e.g. race conditions when evaluating the results of the templates 8 | 9 | workflows: 10 | - template: workflow/match-1.yaml 11 | subtemplates: 12 | - template: workflow/nomatch-1.yaml 13 | subtemplates: 14 | - template: workflow/match-2.yaml 15 | - template: workflow/match-3.yaml 16 | - template: workflow/match-2.yaml 17 | matchers: 18 | - name: test-matcher 19 | subtemplates: 20 | - template: workflow/nomatch-1.yaml 21 | subtemplates: 22 | - template: workflow/match-1.yaml 23 | - template: workflow/match-3.yaml 24 | -------------------------------------------------------------------------------- /integration_tests/workflow/condition-matched.yaml: -------------------------------------------------------------------------------- 1 | id: condition-matched-workflow 2 | 3 | info: 4 | name: Condition Matched Workflow 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/match-1.yaml 10 | subtemplates: 11 | - template: workflow/match-2.yaml -------------------------------------------------------------------------------- /integration_tests/workflow/condition-unmatched.yaml: -------------------------------------------------------------------------------- 1 | id: condition-unmatched-workflow 2 | 3 | info: 4 | name: Condition UnMatched Workflow 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/nomatch-1.yaml 10 | subtemplates: 11 | - template: workflow/match-2.yaml -------------------------------------------------------------------------------- /integration_tests/workflow/dns-value-share-template-1.yaml: -------------------------------------------------------------------------------- 1 | id: dns-value-sharing-template1 2 | 3 | info: 4 | name: dns-value-sharing-template1 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" 10 | type: A 11 | 12 | extractors: 13 | - type: regex 14 | name: extracted 15 | group: 1 16 | regex: 17 | - "IN\tA\t(.+)" -------------------------------------------------------------------------------- /integration_tests/workflow/dns-value-share-template-2.yaml: -------------------------------------------------------------------------------- 1 | id: dns-value-sharing-template2 2 | 3 | info: 4 | name: dns-value-sharing-template2 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{extracted}}" 10 | type: PTR -------------------------------------------------------------------------------- /integration_tests/workflow/dns-value-share-template-3.yaml: -------------------------------------------------------------------------------- 1 | id: value-sharing-template2 2 | 3 | info: 4 | name: value-sharing-template2 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET / HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | {{extracted}} 15 | 16 | matchers: 17 | - type: word 18 | words: 19 | - "ok" -------------------------------------------------------------------------------- /integration_tests/workflow/dns-value-share-workflow.yaml: -------------------------------------------------------------------------------- 1 | id: dns-value-sharing-workflow 2 | info: 3 | name: DNS Value Sharing Test 4 | author: pdteam 5 | severity: info 6 | 7 | workflows: 8 | - template: workflow/dns-value-share-template-1.yaml 9 | subtemplates: 10 | - template: workflow/dns-value-share-template-2.yaml 11 | - template: workflow/dns-value-share-template-3.yaml -------------------------------------------------------------------------------- /integration_tests/workflow/headless-1.yaml: -------------------------------------------------------------------------------- 1 | id: headless-1 2 | info: 3 | name: Headless 1 4 | author: pdteam 5 | severity: info 6 | tags: headless 7 | 8 | headless: 9 | - steps: 10 | - action: navigate 11 | args: 12 | url: "{{BaseURL}}/headless1" 13 | 14 | - action: waitload 15 | -------------------------------------------------------------------------------- /integration_tests/workflow/http-1.yaml: -------------------------------------------------------------------------------- 1 | id: http1 2 | 3 | info: 4 | name: http1 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}/http1" -------------------------------------------------------------------------------- /integration_tests/workflow/http-2.yaml: -------------------------------------------------------------------------------- 1 | id: http2 2 | 3 | info: 4 | name: http2 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}/http2" -------------------------------------------------------------------------------- /integration_tests/workflow/http-3.yaml: -------------------------------------------------------------------------------- 1 | id: http3 2 | 3 | info: 4 | name: http3 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}/http3" -------------------------------------------------------------------------------- /integration_tests/workflow/http-value-share-template-1.yaml: -------------------------------------------------------------------------------- 1 | id: value-sharing-template1 2 | 3 | info: 4 | name: value-sharing-template1 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - path: 10 | - "{{BaseURL}}/path1" 11 | extractors: 12 | - type: regex 13 | part: body 14 | name: extracted 15 | regex: 16 | - 'href="(.*)"' 17 | group: 1 -------------------------------------------------------------------------------- /integration_tests/workflow/http-value-share-template-2.yaml: -------------------------------------------------------------------------------- 1 | id: value-sharing-template2 2 | 3 | info: 4 | name: value-sharing-template2 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | GET /path2 HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | {{extracted}} 15 | 16 | matchers: 17 | - type: word 18 | words: 19 | - "test-value" -------------------------------------------------------------------------------- /integration_tests/workflow/http-value-share-workflow.yaml: -------------------------------------------------------------------------------- 1 | id: http-value-sharing-workflow 2 | info: 3 | name: HTTP Value Sharing Test 4 | author: pdteam 5 | severity: info 6 | 7 | workflows: 8 | - template: workflow/http-value-share-template-1.yaml 9 | subtemplates: 10 | - template: workflow/http-value-share-template-2.yaml -------------------------------------------------------------------------------- /integration_tests/workflow/match-1.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "This is test matcher text" -------------------------------------------------------------------------------- /integration_tests/workflow/match-2.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-another 2 | 3 | info: 4 | name: Basic Another GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | name: test-matcher 15 | words: 16 | - "This is test matcher text" -------------------------------------------------------------------------------- /integration_tests/workflow/match-3.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-third 2 | 3 | info: 4 | name: Basic 3rd GET Request 5 | author: tovask 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | name: test-matcher-3 15 | words: 16 | - "This is test matcher text" 17 | -------------------------------------------------------------------------------- /integration_tests/workflow/matcher-name.yaml: -------------------------------------------------------------------------------- 1 | id: matcher-name-workflow 2 | 3 | info: 4 | name: Matcher Name Workflow 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/match-2.yaml 10 | matchers: 11 | - name: test-matcher 12 | subtemplates: 13 | - template: workflow/match-1.yaml -------------------------------------------------------------------------------- /integration_tests/workflow/multimatch-value-share-template.yaml: -------------------------------------------------------------------------------- 1 | id: multimatch-value-share-template 2 | 3 | info: 4 | name: MultiMatch Value Share Template 5 | author: tovask 6 | severity: info 7 | 8 | http: 9 | - path: 10 | - "{{BaseURL}}/path1?v=1" 11 | - "{{BaseURL}}/path1?v=2" 12 | matchers: 13 | - type: word 14 | name: test-matcher 15 | words: 16 | - "href" 17 | extractors: 18 | - type: regex 19 | part: body 20 | name: extracted 21 | regex: 22 | - 'href="(.*)"' 23 | group: 1 24 | -------------------------------------------------------------------------------- /integration_tests/workflow/multimatch-value-share-workflow.yaml: -------------------------------------------------------------------------------- 1 | id: multimatch-value-share-workflow 2 | 3 | info: 4 | name: MultiMatch Value Share Workflow 5 | author: tovask 6 | severity: info 7 | description: Workflow to test value sharing when multiple matches occur in the extractor template 8 | 9 | workflows: 10 | - template: workflow/multimatch-value-share-template.yaml 11 | subtemplates: 12 | - template: workflow/match-1.yaml 13 | subtemplates: 14 | - template: workflow/http-value-share-template-2.yaml 15 | - template: workflow/multimatch-value-share-template.yaml 16 | matchers: 17 | - name: test-matcher 18 | subtemplates: 19 | - template: workflow/match-1.yaml 20 | subtemplates: 21 | - template: workflow/http-value-share-template-2.yaml 22 | -------------------------------------------------------------------------------- /integration_tests/workflow/multiprotocol-value-share-template.yaml: -------------------------------------------------------------------------------- 1 | id: multiprotocol-value-sharing-template 2 | 3 | info: 4 | name: MultiProtocol Value Sharing Template 5 | author: tovask 6 | severity: info 7 | 8 | dns: 9 | - name: "{{extracted}}" 10 | type: PTR 11 | matchers: 12 | - type: word 13 | words: 14 | - "blog.projectdiscovery.io" 15 | 16 | http: 17 | - path: 18 | - "{{BaseURL}}/path2?extracted={{extracted}}" 19 | matchers: 20 | - type: word 21 | words: 22 | - "blog.projectdiscovery.io" 23 | -------------------------------------------------------------------------------- /integration_tests/workflow/multiprotocol-value-share-workflow.yaml: -------------------------------------------------------------------------------- 1 | id: multiprotocol-value-sharing-workflow 2 | 3 | info: 4 | name: MultiProtocol Value Sharing Workflow 5 | author: tovask 6 | severity: info 7 | 8 | workflows: 9 | - template: workflow/http-value-share-template-1.yaml 10 | subtemplates: 11 | - template: workflow/multiprotocol-value-share-template.yaml 12 | -------------------------------------------------------------------------------- /integration_tests/workflow/nomatch-1.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get-nomatch 2 | 3 | info: 4 | name: Basic GET Request NoMatch 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "Random" -------------------------------------------------------------------------------- /integration_tests/workflow/shared-cookie.yaml: -------------------------------------------------------------------------------- 1 | id: workflow-shared-cookies 2 | 3 | info: 4 | name: Test Workflow Shared Cookies 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | # store cookies to standard http client cookie-jar 10 | - template: workflow/http-1.yaml 11 | - template: workflow/http-2.yaml 12 | # store cookie in native browser context 13 | - template: workflow/headless-1.yaml 14 | # retrieve 2 standard library cookies + headless cookie 15 | - template: workflow/http-3.yaml -------------------------------------------------------------------------------- /internal/pdcp/utils.go: -------------------------------------------------------------------------------- 1 | package pdcp 2 | 3 | import ( 4 | pdcpauth "github.com/projectdiscovery/utils/auth/pdcp" 5 | urlutil "github.com/projectdiscovery/utils/url" 6 | ) 7 | 8 | func getScanDashBoardURL(id string, teamID string) string { 9 | ux, _ := urlutil.Parse(pdcpauth.DashBoardURL) 10 | ux.Path = "/scans/" + id 11 | if ux.Params == nil { 12 | ux.Params = urlutil.NewOrderedParams() 13 | } 14 | if teamID != "" { 15 | ux.Params.Add("team_id", teamID) 16 | } else { 17 | ux.Params.Add("team_id", NoneTeamID) 18 | } 19 | ux.Update() 20 | return ux.String() 21 | } 22 | 23 | type uploadResponse struct { 24 | ID string `json:"id"` 25 | Message string `json:"message"` 26 | } 27 | -------------------------------------------------------------------------------- /pkg/authprovider/authx/basic_auth.go: -------------------------------------------------------------------------------- 1 | package authx 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/projectdiscovery/retryablehttp-go" 7 | ) 8 | 9 | var ( 10 | _ AuthStrategy = &BasicAuthStrategy{} 11 | ) 12 | 13 | // BasicAuthStrategy is a strategy for basic auth 14 | type BasicAuthStrategy struct { 15 | Data *Secret 16 | } 17 | 18 | // NewBasicAuthStrategy creates a new basic auth strategy 19 | func NewBasicAuthStrategy(data *Secret) *BasicAuthStrategy { 20 | return &BasicAuthStrategy{Data: data} 21 | } 22 | 23 | // Apply applies the basic auth strategy to the request 24 | func (s *BasicAuthStrategy) Apply(req *http.Request) { 25 | req.SetBasicAuth(s.Data.Username, s.Data.Password) 26 | } 27 | 28 | // ApplyOnRR applies the basic auth strategy to the retryable request 29 | func (s *BasicAuthStrategy) ApplyOnRR(req *retryablehttp.Request) { 30 | req.SetBasicAuth(s.Data.Username, s.Data.Password) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/authprovider/authx/file_test.go: -------------------------------------------------------------------------------- 1 | package authx 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestSecretsUnmarshal(t *testing.T) { 10 | loc := "testData/example-auth.yaml" 11 | data, err := GetAuthDataFromFile(loc) 12 | require.Nil(t, err, "could not read secrets file") 13 | require.NotNil(t, data, "could not read secrets file") 14 | for _, s := range data.Secrets { 15 | require.Nil(t, s.Validate(), "could not validate secret") 16 | } 17 | for _, d := range data.Dynamic { 18 | require.Nil(t, d.Validate(), "could not validate dynamic") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pkg/catalog/config/ignorefile.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/projectdiscovery/gologger" 7 | "gopkg.in/yaml.v2" 8 | ) 9 | 10 | // IgnoreFile is an internal nuclei template blocking configuration file 11 | type IgnoreFile struct { 12 | Tags []string `yaml:"tags"` 13 | Files []string `yaml:"files"` 14 | } 15 | 16 | // ReadIgnoreFile reads the nuclei ignore file returning blocked tags and paths 17 | func ReadIgnoreFile() IgnoreFile { 18 | file, err := os.Open(DefaultConfig.GetIgnoreFilePath()) 19 | if err != nil { 20 | gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n", err) 21 | return IgnoreFile{} 22 | } 23 | defer file.Close() 24 | 25 | ignore := IgnoreFile{} 26 | if err := yaml.NewDecoder(file).Decode(&ignore); err != nil { 27 | gologger.Error().Msgf("Could not parse nuclei-ignore file: %s\n", err) 28 | return IgnoreFile{} 29 | } 30 | return ignore 31 | } 32 | -------------------------------------------------------------------------------- /pkg/catalog/disk/known-files.go: -------------------------------------------------------------------------------- 1 | package disk 2 | 3 | var knownConfigFiles = []string{"cves.json", "contributors.json", "TEMPLATES-STATS.json"} 4 | -------------------------------------------------------------------------------- /pkg/core/engine_test.go: -------------------------------------------------------------------------------- 1 | package core 2 | -------------------------------------------------------------------------------- /pkg/fuzz/dataformat/raw.go: -------------------------------------------------------------------------------- 1 | package dataformat 2 | 3 | type Raw struct{} 4 | 5 | var ( 6 | _ DataFormat = &Raw{} 7 | ) 8 | 9 | // NewRaw returns a new Raw encoder 10 | func NewRaw() *Raw { 11 | return &Raw{} 12 | } 13 | 14 | // IsType returns true if the data is Raw encoded 15 | func (r *Raw) IsType(data string) bool { 16 | return false 17 | } 18 | 19 | // Encode encodes the data into Raw format 20 | func (r *Raw) Encode(data KV) (string, error) { 21 | return data.Get("value").(string), nil 22 | } 23 | 24 | // Decode decodes the data from Raw format 25 | func (r *Raw) Decode(data string) (KV, error) { 26 | return KVMap(map[string]interface{}{ 27 | "value": data, 28 | }), nil 29 | } 30 | 31 | // Name returns the name of the encoder 32 | func (r *Raw) Name() string { 33 | return RawDataFormat 34 | } 35 | -------------------------------------------------------------------------------- /pkg/fuzz/doc.go: -------------------------------------------------------------------------------- 1 | // Package fuzz contains the fuzzing functionality for dynamic 2 | // fuzzing of HTTP requests and its respective implementation. 3 | package fuzz 4 | -------------------------------------------------------------------------------- /pkg/fuzz/parts_test.go: -------------------------------------------------------------------------------- 1 | // TODO: Write tests 2 | package fuzz 3 | -------------------------------------------------------------------------------- /pkg/fuzz/stats/db.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import ( 4 | _ "embed" 5 | 6 | _ "github.com/mattn/go-sqlite3" 7 | ) 8 | 9 | type StatsDatabase interface { 10 | Close() 11 | 12 | InsertComponent(event ComponentEvent) error 13 | InsertMatchedRecord(event FuzzingEvent) error 14 | InsertError(event ErrorEvent) error 15 | } 16 | -------------------------------------------------------------------------------- /pkg/fuzz/stats/db_test.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func Test_NewStatsDatabase(t *testing.T) { 10 | db, err := NewSimpleStats() 11 | require.NoError(t, err) 12 | 13 | err = db.InsertMatchedRecord(FuzzingEvent{ 14 | URL: "http://localhost:8080/login", 15 | TemplateID: "apache-struts2-001", 16 | ComponentType: "path", 17 | ComponentName: "/login", 18 | PayloadSent: "/login'\"><", 19 | StatusCode: 401, 20 | }) 21 | require.NoError(t, err) 22 | 23 | //os.Remove("test.stats.db") 24 | } 25 | -------------------------------------------------------------------------------- /pkg/input/provider/list/utils.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | type ipOptions struct { 4 | ScanAllIPs bool 5 | IPV4 bool 6 | IPV6 bool 7 | } 8 | -------------------------------------------------------------------------------- /pkg/input/types/probe.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // InputLivenessProbe is an interface for probing the liveness of an input 4 | type InputLivenessProbe interface { 5 | // ProbeURL probes the scheme for a URL. first HTTPS is tried 6 | ProbeURL(input string) (string, error) 7 | // Close closes the liveness probe 8 | Close() error 9 | } 10 | -------------------------------------------------------------------------------- /pkg/installer/doc.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | // package install provides helper functions for all download and installation of following tasks: 4 | // 1. downloading and install nuclei templates 5 | // 2. download and update nuclei binary (i.e self update) 6 | // 3. version check for nuclei binary & templates 7 | -------------------------------------------------------------------------------- /pkg/installer/versioncheck_test.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" 7 | "github.com/projectdiscovery/utils/generic" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestVersionCheck(t *testing.T) { 12 | err := NucleiVersionCheck() 13 | require.Nil(t, err) 14 | cfg := config.DefaultConfig 15 | if generic.EqualsAny("", cfg.LatestNucleiIgnoreHash, cfg.LatestNucleiVersion, cfg.LatestNucleiTemplatesVersion) { 16 | // all above values cannot be empty 17 | t.Errorf("something went wrong got empty response nuclei-version=%v templates-version=%v ignore-hash=%v", cfg.LatestNucleiVersion, cfg.LatestNucleiTemplatesVersion, cfg.LatestNucleiIgnoreHash) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pkg/js/THANKS.md: -------------------------------------------------------------------------------- 1 | # THANKS 2 | 3 | - https://github.com/dop251/goja - Pure Go Javascript VM used by nuclei JS layer. 4 | - https://github.com/gogap/gojs-tool - Inspiration for code generation used in JS Libraries addition. 5 | - https://github.com/ropnop/kerbrute - Kerberos Module of JS layer 6 | - https://github.com/praetorian-inc/fingerprintx - A lot of Network Protocol fingerprinting functionality is used from `fingerprintx` package. 7 | - https://github.com/zmap/zgrab2 - Used for SMB and SSH protocol handshake Metadata gathering. 8 | 9 | A lot of other Go based libraries are used in the javascript layer. Thanks goes to the creators and maintainers. -------------------------------------------------------------------------------- /pkg/js/compiler/init.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/types" 5 | ) 6 | 7 | // jsprotocolInit 8 | 9 | var ( 10 | PoolingJsVmConcurrency = 100 11 | NonPoolingVMConcurrency = 20 12 | ) 13 | 14 | // Init initializes the javascript protocol 15 | func Init(opts *types.Options) error { 16 | 17 | if opts.JsConcurrency < 100 { 18 | // 100 is reasonable default 19 | opts.JsConcurrency = 100 20 | } 21 | PoolingJsVmConcurrency = opts.JsConcurrency 22 | PoolingJsVmConcurrency -= NonPoolingVMConcurrency 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /pkg/js/compiler/non-pool.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/dop251/goja" 7 | syncutil "github.com/projectdiscovery/utils/sync" 8 | ) 9 | 10 | var ( 11 | ephemeraljsc *syncutil.AdaptiveWaitGroup 12 | lazyFixedSgInit = sync.OnceFunc(func() { 13 | ephemeraljsc, _ = syncutil.New(syncutil.WithSize(NonPoolingVMConcurrency)) 14 | }) 15 | ) 16 | 17 | func executeWithoutPooling(p *goja.Program, args *ExecuteArgs, opts *ExecuteOptions) (result goja.Value, err error) { 18 | lazyFixedSgInit() 19 | ephemeraljsc.Add() 20 | defer ephemeraljsc.Done() 21 | runtime := createNewRuntime() 22 | return executeWithRuntime(runtime, p, args, opts) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/js/devtools/bindgen/INSTALL.md: -------------------------------------------------------------------------------- 1 | # INSTALL 2 | 3 | 1. Requires `js-beautify` node plugin installed in `$PATH`. 4 | 2. Requires `gofmt` installed in `$PATH`. 5 | -------------------------------------------------------------------------------- /pkg/js/devtools/bindgen/README.md: -------------------------------------------------------------------------------- 1 | ## bindgen (aka bindings generator) 2 | 3 | bindgen is a tool that automatically generated bindings for native go packages with 'goja' 4 | 5 | Native Go packages are available [here](../../libs/) 6 | 7 | Generated Output is available [here](../../generated/) 8 | 9 | bindgen generates 3 different types of outputs 10 | 11 | - `go` => this directory contains corresponding goja bindings (actual bindings code) ex: [kerberos.go](../../generated/go/libkerberos/kerberos.go) 12 | - `js` => this is more of a javascript **representation** of all exposed functions and types etc in javascript ex: [kerberos.js](../../generated/js/libkerberos/kerberos.js) and does not server any functional purpose other than reference 13 | - `markdown` => autogenerated markdown documentation for each library / package ex: [kerberos.md](../../generated/markdown/libkerberos/kerberos.md) 14 | 15 | -------------------------------------------------------------------------------- /pkg/js/devtools/tsgen/README.md: -------------------------------------------------------------------------------- 1 | # tsgen 2 | 3 | tsgen is devtool to generate dummy typescript code for goja node modules written in golang. These generated typescript code can be compiled to generate .d.ts files to provide intellisense to editors like vscode and documentation for the node modules. -------------------------------------------------------------------------------- /pkg/js/generated/README.md: -------------------------------------------------------------------------------- 1 | ## generated 2 | 3 | !! Warning !! This is generated code, do not edit manually !! 4 | 5 | To make any changes to this code, please refer to [bindgen](../devtools/bindgen/README.md) -------------------------------------------------------------------------------- /pkg/js/generated/go/libbytes/bytes.go: -------------------------------------------------------------------------------- 1 | package bytes 2 | 3 | import ( 4 | lib_bytes "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/bytes" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/bytes") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "NewBuffer": lib_bytes.NewBuffer, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "Buffer": lib_bytes.NewBuffer, 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libfs/fs.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | lib_fs "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/fs" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/fs") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "ListDir": lib_fs.ListDir, 19 | "ReadFile": lib_fs.ReadFile, 20 | "ReadFileAsString": lib_fs.ReadFileAsString, 21 | "ReadFilesFromDir": lib_fs.ReadFilesFromDir, 22 | 23 | // Var and consts 24 | 25 | // Objects / Classes 26 | 27 | }, 28 | ).Register() 29 | } 30 | 31 | func Enable(runtime *goja.Runtime) { 32 | module.Enable(runtime) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libgoconsole/goconsole.go: -------------------------------------------------------------------------------- 1 | package goconsole 2 | 3 | import ( 4 | lib_goconsole "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/goconsole" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/goconsole") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "NewGoConsolePrinter": lib_goconsole.NewGoConsolePrinter, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "GoConsolePrinter": gojs.GetClassConstructor[lib_goconsole.GoConsolePrinter](&lib_goconsole.GoConsolePrinter{}), 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libmssql/mssql.go: -------------------------------------------------------------------------------- 1 | package mssql 2 | 3 | import ( 4 | lib_mssql "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/mssql" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/mssql") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | 19 | // Var and consts 20 | 21 | // Objects / Classes 22 | "MSSQLClient": gojs.GetClassConstructor[lib_mssql.MSSQLClient](&lib_mssql.MSSQLClient{}), 23 | }, 24 | ).Register() 25 | } 26 | 27 | func Enable(runtime *goja.Runtime) { 28 | module.Enable(runtime) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libmysql/mysql.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import ( 4 | lib_mysql "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/mysql" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/mysql") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "BuildDSN": lib_mysql.BuildDSN, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "MySQLClient": gojs.GetClassConstructor[lib_mysql.MySQLClient](&lib_mysql.MySQLClient{}), 24 | "MySQLInfo": gojs.GetClassConstructor[lib_mysql.MySQLInfo](&lib_mysql.MySQLInfo{}), 25 | "MySQLOptions": gojs.GetClassConstructor[lib_mysql.MySQLOptions](&lib_mysql.MySQLOptions{}), 26 | }, 27 | ).Register() 28 | } 29 | 30 | func Enable(runtime *goja.Runtime) { 31 | module.Enable(runtime) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libnet/net.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | lib_net "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/net" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/net") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "Open": lib_net.Open, 19 | "OpenTLS": lib_net.OpenTLS, 20 | 21 | // Var and consts 22 | 23 | // Objects / Classes 24 | "NetConn": gojs.GetClassConstructor[lib_net.NetConn](&lib_net.NetConn{}), 25 | }, 26 | ).Register() 27 | } 28 | 29 | func Enable(runtime *goja.Runtime) { 30 | module.Enable(runtime) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/js/generated/go/liboracle/oracle.go: -------------------------------------------------------------------------------- 1 | package oracle 2 | 3 | import ( 4 | lib_oracle "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/oracle" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/oracle") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "IsOracle": lib_oracle.IsOracle, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "IsOracleResponse": gojs.GetClassConstructor[lib_oracle.IsOracleResponse](&lib_oracle.IsOracleResponse{}), 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libpop3/pop3.go: -------------------------------------------------------------------------------- 1 | package pop3 2 | 3 | import ( 4 | lib_pop3 "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/pop3" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/pop3") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "IsPOP3": lib_pop3.IsPOP3, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "IsPOP3Response": gojs.GetClassConstructor[lib_pop3.IsPOP3Response](&lib_pop3.IsPOP3Response{}), 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libpostgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | lib_postgres "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/postgres" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/postgres") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | 19 | // Var and consts 20 | 21 | // Objects / Classes 22 | "PGClient": gojs.GetClassConstructor[lib_postgres.PGClient](&lib_postgres.PGClient{}), 23 | }, 24 | ).Register() 25 | } 26 | 27 | func Enable(runtime *goja.Runtime) { 28 | module.Enable(runtime) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/js/generated/go/librdp/rdp.go: -------------------------------------------------------------------------------- 1 | package rdp 2 | 3 | import ( 4 | lib_rdp "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/rdp" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/rdp") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "CheckRDPAuth": lib_rdp.CheckRDPAuth, 19 | "IsRDP": lib_rdp.IsRDP, 20 | 21 | // Var and consts 22 | 23 | // Objects / Classes 24 | "CheckRDPAuthResponse": gojs.GetClassConstructor[lib_rdp.CheckRDPAuthResponse](&lib_rdp.CheckRDPAuthResponse{}), 25 | "IsRDPResponse": gojs.GetClassConstructor[lib_rdp.IsRDPResponse](&lib_rdp.IsRDPResponse{}), 26 | }, 27 | ).Register() 28 | } 29 | 30 | func Enable(runtime *goja.Runtime) { 31 | module.Enable(runtime) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libredis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | lib_redis "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/redis" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/redis") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "Connect": lib_redis.Connect, 19 | "GetServerInfo": lib_redis.GetServerInfo, 20 | "GetServerInfoAuth": lib_redis.GetServerInfoAuth, 21 | "IsAuthenticated": lib_redis.IsAuthenticated, 22 | "RunLuaScript": lib_redis.RunLuaScript, 23 | 24 | // Var and consts 25 | 26 | // Objects / Classes 27 | 28 | }, 29 | ).Register() 30 | } 31 | 32 | func Enable(runtime *goja.Runtime) { 33 | module.Enable(runtime) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/js/generated/go/librsync/rsync.go: -------------------------------------------------------------------------------- 1 | package rsync 2 | 3 | import ( 4 | lib_rsync "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/rsync" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/rsync") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "IsRsync": lib_rsync.IsRsync, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "IsRsyncResponse": gojs.GetClassConstructor[lib_rsync.IsRsyncResponse](&lib_rsync.IsRsyncResponse{}), 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libsmb/smb.go: -------------------------------------------------------------------------------- 1 | package smb 2 | 3 | import ( 4 | lib_smb "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/smb" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/smb") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | 19 | // Var and consts 20 | 21 | // Objects / Classes 22 | "SMBClient": gojs.GetClassConstructor[lib_smb.SMBClient](&lib_smb.SMBClient{}), 23 | }, 24 | ).Register() 25 | } 26 | 27 | func Enable(runtime *goja.Runtime) { 28 | module.Enable(runtime) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libsmtp/smtp.go: -------------------------------------------------------------------------------- 1 | package smtp 2 | 3 | import ( 4 | lib_smtp "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/smtp" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/smtp") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "NewSMTPClient": lib_smtp.NewSMTPClient, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "Client": lib_smtp.NewSMTPClient, 24 | "SMTPMessage": gojs.GetClassConstructor[lib_smtp.SMTPMessage](&lib_smtp.SMTPMessage{}), 25 | "SMTPResponse": gojs.GetClassConstructor[lib_smtp.SMTPResponse](&lib_smtp.SMTPResponse{}), 26 | }, 27 | ).Register() 28 | } 29 | 30 | func Enable(runtime *goja.Runtime) { 31 | module.Enable(runtime) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libssh/ssh.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | lib_ssh "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ssh" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/ssh") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | 19 | // Var and consts 20 | 21 | // Objects / Classes 22 | "SSHClient": gojs.GetClassConstructor[lib_ssh.SSHClient](&lib_ssh.SSHClient{}), 23 | }, 24 | ).Register() 25 | } 26 | 27 | func Enable(runtime *goja.Runtime) { 28 | module.Enable(runtime) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libstructs/structs.go: -------------------------------------------------------------------------------- 1 | package structs 2 | 3 | import ( 4 | lib_structs "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/structs") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "Pack": lib_structs.Pack, 19 | "StructsCalcSize": lib_structs.StructsCalcSize, 20 | "Unpack": lib_structs.Unpack, 21 | 22 | // Var and consts 23 | 24 | // Objects / Classes 25 | 26 | }, 27 | ).Register() 28 | } 29 | 30 | func Enable(runtime *goja.Runtime) { 31 | module.Enable(runtime) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libtelnet/telnet.go: -------------------------------------------------------------------------------- 1 | package telnet 2 | 3 | import ( 4 | lib_telnet "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/telnet" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/telnet") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "IsTelnet": lib_telnet.IsTelnet, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "IsTelnetResponse": gojs.GetClassConstructor[lib_telnet.IsTelnetResponse](&lib_telnet.IsTelnetResponse{}), 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/go/libvnc/vnc.go: -------------------------------------------------------------------------------- 1 | package vnc 2 | 3 | import ( 4 | lib_vnc "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/vnc" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" 8 | ) 9 | 10 | var ( 11 | module = gojs.NewGojaModule("nuclei/vnc") 12 | ) 13 | 14 | func init() { 15 | module.Set( 16 | gojs.Objects{ 17 | // Functions 18 | "IsVNC": lib_vnc.IsVNC, 19 | 20 | // Var and consts 21 | 22 | // Objects / Classes 23 | "IsVNCResponse": gojs.GetClassConstructor[lib_vnc.IsVNCResponse](&lib_vnc.IsVNCResponse{}), 24 | }, 25 | ).Register() 26 | } 27 | 28 | func Enable(runtime *goja.Runtime) { 29 | module.Enable(runtime) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/goconsole.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * NewGoConsolePrinter Function 5 | */ 6 | export function NewGoConsolePrinter(): GoConsolePrinter { 7 | return new GoConsolePrinter(); 8 | } 9 | 10 | 11 | 12 | /** 13 | */ 14 | export class GoConsolePrinter { 15 | 16 | 17 | // Constructor of GoConsolePrinter 18 | constructor() {} 19 | /** 20 | * Log Method 21 | */ 22 | public Log(msg: string): void { 23 | return; 24 | } 25 | 26 | 27 | /** 28 | * Warn Method 29 | */ 30 | public Warn(msg: string): void { 31 | return; 32 | } 33 | 34 | 35 | /** 36 | * Error Method 37 | */ 38 | public Error(msg: string): void { 39 | return; 40 | } 41 | 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/index.ts: -------------------------------------------------------------------------------- 1 | export * as bytes from './bytes'; 2 | export * as fs from './fs'; 3 | export * as goconsole from './goconsole'; 4 | export * as ikev2 from './ikev2'; 5 | export * as kerberos from './kerberos'; 6 | export * as ldap from './ldap'; 7 | export * as mssql from './mssql'; 8 | export * as mysql from './mysql'; 9 | export * as net from './net'; 10 | export * as oracle from './oracle'; 11 | export * as pop3 from './pop3'; 12 | export * as postgres from './postgres'; 13 | export * as rdp from './rdp'; 14 | export * as redis from './redis'; 15 | export * as rsync from './rsync'; 16 | export * as smb from './smb'; 17 | export * as smtp from './smtp'; 18 | export * as ssh from './ssh'; 19 | export * as structs from './structs'; 20 | export * as telnet from './telnet'; 21 | export * as vnc from './vnc'; 22 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/oracle.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * IsOracle checks if a host is running an Oracle server 5 | * @example 6 | * ```javascript 7 | * const oracle = require('nuclei/oracle'); 8 | * const isOracle = oracle.IsOracle('acme.com', 1521); 9 | * log(toJSON(isOracle)); 10 | * ``` 11 | */ 12 | export function IsOracle(host: string, port: number): IsOracleResponse | null { 13 | return null; 14 | } 15 | 16 | 17 | 18 | /** 19 | * IsOracleResponse is the response from the IsOracle function. 20 | * this is returned by IsOracle function. 21 | * @example 22 | * ```javascript 23 | * const oracle = require('nuclei/oracle'); 24 | * const isOracle = oracle.IsOracle('acme.com', 1521); 25 | * ``` 26 | */ 27 | export interface IsOracleResponse { 28 | 29 | IsOracle?: boolean, 30 | 31 | Banner?: string, 32 | } 33 | 34 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/pop3.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * IsPOP3 checks if a host is running a POP3 server. 5 | * @example 6 | * ```javascript 7 | * const pop3 = require('nuclei/pop3'); 8 | * const isPOP3 = pop3.IsPOP3('acme.com', 110); 9 | * log(toJSON(isPOP3)); 10 | * ``` 11 | */ 12 | export function IsPOP3(host: string, port: number): IsPOP3Response | null { 13 | return null; 14 | } 15 | 16 | 17 | 18 | /** 19 | * IsPOP3Response is the response from the IsPOP3 function. 20 | * this is returned by IsPOP3 function. 21 | * @example 22 | * ```javascript 23 | * const pop3 = require('nuclei/pop3'); 24 | * const isPOP3 = pop3.IsPOP3('acme.com', 110); 25 | * log(toJSON(isPOP3)); 26 | * ``` 27 | */ 28 | export interface IsPOP3Response { 29 | 30 | IsPOP3?: boolean, 31 | 32 | Banner?: string, 33 | } 34 | 35 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/rsync.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * IsRsync checks if a host is running a Rsync server. 5 | * @example 6 | * ```javascript 7 | * const rsync = require('nuclei/rsync'); 8 | * const isRsync = rsync.IsRsync('acme.com', 873); 9 | * log(toJSON(isRsync)); 10 | * ``` 11 | */ 12 | export function IsRsync(host: string, port: number): IsRsyncResponse | null { 13 | return null; 14 | } 15 | 16 | 17 | 18 | /** 19 | * IsRsyncResponse is the response from the IsRsync function. 20 | * this is returned by IsRsync function. 21 | * @example 22 | * ```javascript 23 | * const rsync = require('nuclei/rsync'); 24 | * const isRsync = rsync.IsRsync('acme.com', 873); 25 | * log(toJSON(isRsync)); 26 | * ``` 27 | */ 28 | export interface IsRsyncResponse { 29 | 30 | IsRsync?: boolean, 31 | 32 | Banner?: string, 33 | } 34 | 35 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/telnet.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * IsTelnet checks if a host is running a Telnet server. 5 | * @example 6 | * ```javascript 7 | * const telnet = require('nuclei/telnet'); 8 | * const isTelnet = telnet.IsTelnet('acme.com', 23); 9 | * log(toJSON(isTelnet)); 10 | * ``` 11 | */ 12 | export function IsTelnet(host: string, port: number): IsTelnetResponse | null { 13 | return null; 14 | } 15 | 16 | 17 | 18 | /** 19 | * IsTelnetResponse is the response from the IsTelnet function. 20 | * this is returned by IsTelnet function. 21 | * @example 22 | * ```javascript 23 | * const telnet = require('nuclei/telnet'); 24 | * const isTelnet = telnet.IsTelnet('acme.com', 23); 25 | * log(toJSON(isTelnet)); 26 | * ``` 27 | */ 28 | export interface IsTelnetResponse { 29 | 30 | IsTelnet?: boolean, 31 | 32 | Banner?: string, 33 | } 34 | 35 | -------------------------------------------------------------------------------- /pkg/js/generated/ts/vnc.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * IsVNC checks if a host is running a VNC server. 5 | * It returns a boolean indicating if the host is running a VNC server 6 | * and the banner of the VNC server. 7 | * @example 8 | * ```javascript 9 | * const vnc = require('nuclei/vnc'); 10 | * const isVNC = vnc.IsVNC('acme.com', 5900); 11 | * log(toJSON(isVNC)); 12 | * ``` 13 | */ 14 | export function IsVNC(host: string, port: number): IsVNCResponse | null { 15 | return null; 16 | } 17 | 18 | 19 | 20 | /** 21 | * IsVNCResponse is the response from the IsVNC function. 22 | * @example 23 | * ```javascript 24 | * const vnc = require('nuclei/vnc'); 25 | * const isVNC = vnc.IsVNC('acme.com', 5900); 26 | * log(toJSON(isVNC)); 27 | * ``` 28 | */ 29 | export interface IsVNCResponse { 30 | 31 | IsVNC?: boolean, 32 | 33 | Banner?: string, 34 | } 35 | 36 | -------------------------------------------------------------------------------- /pkg/js/global/exports.js: -------------------------------------------------------------------------------- 1 | exports = { 2 | // General 3 | dump_json: dump_json, 4 | to_json: to_json, 5 | to_array: to_array, 6 | hex_to_ascii: hex_to_ascii, 7 | 8 | // Active Directory 9 | getDomainControllerName: getDomainControllerName, 10 | }; 11 | -------------------------------------------------------------------------------- /pkg/js/global/js/dump.js: -------------------------------------------------------------------------------- 1 | // dump_json dumps the data as JSON to the console. 2 | // It returns beautified JSON. 3 | function dump_json(data) { 4 | console.log(JSON.stringify(data, null, 2)); 5 | } 6 | 7 | // to_json returns beautified JSON. 8 | function to_json(data) { 9 | return JSON.stringify(data, null, 2); 10 | } 11 | 12 | // to_array sets object type as array 13 | function to_array(data) { 14 | return Object.setPrototypeOf(data, Array.prototype); 15 | } 16 | 17 | // hex_to_ascii converts a hex string to ascii. 18 | function hex_to_ascii(str1) { 19 | var hex = str1.toString(); 20 | var str = ""; 21 | for (var n = 0; n < hex.length; n += 2) { 22 | str += String.fromCharCode(parseInt(hex.substr(n, 2), 16)); 23 | } 24 | return str; 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/global/scripts_test.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/dop251/goja_nodejs/console" 8 | "github.com/dop251/goja_nodejs/require" 9 | ) 10 | 11 | func TestScriptsRuntime(t *testing.T) { 12 | defaultImports = "" 13 | runtime := goja.New() 14 | 15 | registry := new(require.Registry) 16 | registry.Enable(runtime) 17 | console.Enable(runtime) 18 | 19 | err := RegisterNativeScripts(runtime) 20 | if err != nil { 21 | t.Fatal(err) 22 | } 23 | value, err := runtime.RunString("dump_json({a: 1, b: 2})") 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | _ = value 28 | } 29 | -------------------------------------------------------------------------------- /pkg/js/libs/goconsole/log.go: -------------------------------------------------------------------------------- 1 | package goconsole 2 | 3 | import ( 4 | "github.com/dop251/goja_nodejs/console" 5 | "github.com/projectdiscovery/gologger" 6 | ) 7 | 8 | var _ console.Printer = &GoConsolePrinter{} 9 | 10 | // GoConsolePrinter is a console printer for nuclei using gologger 11 | type GoConsolePrinter struct { 12 | logger *gologger.Logger 13 | } 14 | 15 | func NewGoConsolePrinter() *GoConsolePrinter { 16 | return &GoConsolePrinter{ 17 | logger: gologger.DefaultLogger, 18 | } 19 | } 20 | 21 | func (p *GoConsolePrinter) Log(msg string) { 22 | p.logger.Info().Msg(msg) 23 | } 24 | 25 | func (p *GoConsolePrinter) Warn(msg string) { 26 | p.logger.Warning().Msg(msg) 27 | } 28 | 29 | func (p *GoConsolePrinter) Error(msg string) { 30 | p.logger.Error().Msg(msg) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/js/libs/mysql/memo.mysql_private.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package mysql 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizedconnectWithDSN(dsn string) (bool, error) { 12 | hash := "connectWithDSN" + ":" + fmt.Sprint(dsn) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return connectWithDSN(dsn) 16 | }) 17 | if err != nil { 18 | return false, err 19 | } 20 | if value, ok := v.(bool); ok { 21 | return value, nil 22 | } 23 | 24 | return false, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/libs/oracle/memo.oracle.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package oracle 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizedisOracle(host string, port int) (IsOracleResponse, error) { 12 | hash := "isOracle" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return isOracle(host, port) 16 | }) 17 | if err != nil { 18 | return IsOracleResponse{}, err 19 | } 20 | if value, ok := v.(IsOracleResponse); ok { 21 | return value, nil 22 | } 23 | 24 | return IsOracleResponse{}, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/libs/pop3/memo.pop3.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package pop3 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizedisPoP3(host string, port int) (IsPOP3Response, error) { 12 | hash := "isPoP3" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return isPoP3(host, port) 16 | }) 17 | if err != nil { 18 | return IsPOP3Response{}, err 19 | } 20 | if value, ok := v.(IsPOP3Response); ok { 21 | return value, nil 22 | } 23 | 24 | return IsPOP3Response{}, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/libs/rsync/memo.rsync.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package rsync 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizedisRsync(host string, port int) (IsRsyncResponse, error) { 12 | hash := "isRsync" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return isRsync(host, port) 16 | }) 17 | if err != nil { 18 | return IsRsyncResponse{}, err 19 | } 20 | if value, ok := v.(IsRsyncResponse); ok { 21 | return value, nil 22 | } 23 | 24 | return IsRsyncResponse{}, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/libs/smb/memo.smb_private.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package smb 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "time" 9 | 10 | "github.com/praetorian-inc/fingerprintx/pkg/plugins" 11 | 12 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 13 | ) 14 | 15 | func memoizedcollectSMBv2Metadata(host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) { 16 | hash := "collectSMBv2Metadata" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(timeout) 17 | 18 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 19 | return collectSMBv2Metadata(host, port, timeout) 20 | }) 21 | if err != nil { 22 | return nil, err 23 | } 24 | if value, ok := v.(*plugins.ServiceSMB); ok { 25 | return value, nil 26 | } 27 | 28 | return nil, errors.New("could not convert cached result") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/js/libs/smb/memo.smbghost.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package smb 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizeddetectSMBGhost(host string, port int) (bool, error) { 12 | hash := "detectSMBGhost" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return detectSMBGhost(host, port) 16 | }) 17 | if err != nil { 18 | return false, err 19 | } 20 | if value, ok := v.(bool); ok { 21 | return value, nil 22 | } 23 | 24 | return false, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/libs/ssh/memo.ssh.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package ssh 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | 10 | "github.com/zmap/zgrab2/lib/ssh" 11 | ) 12 | 13 | func memoizedconnectSSHInfoMode(opts *connectOptions) (*ssh.HandshakeLog, error) { 14 | hash := "connectSSHInfoMode" + ":" + fmt.Sprint(opts) 15 | 16 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 17 | return connectSSHInfoMode(opts) 18 | }) 19 | if err != nil { 20 | return nil, err 21 | } 22 | if value, ok := v.(*ssh.HandshakeLog); ok { 23 | return value, nil 24 | } 25 | 26 | return nil, errors.New("could not convert cached result") 27 | } 28 | -------------------------------------------------------------------------------- /pkg/js/libs/telnet/memo.telnet.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package telnet 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizedisTelnet(host string, port int) (IsTelnetResponse, error) { 12 | hash := "isTelnet" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return isTelnet(host, port) 16 | }) 17 | if err != nil { 18 | return IsTelnetResponse{}, err 19 | } 20 | if value, ok := v.(IsTelnetResponse); ok { 21 | return value, nil 22 | } 23 | 24 | return IsTelnetResponse{}, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/js/libs/vnc/memo.vnc.go: -------------------------------------------------------------------------------- 1 | // Warning - This is generated code 2 | package vnc 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" 9 | ) 10 | 11 | func memoizedisVNC(host string, port int) (IsVNCResponse, error) { 12 | hash := "isVNC" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) 13 | 14 | v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { 15 | return isVNC(host, port) 16 | }) 17 | if err != nil { 18 | return IsVNCResponse{}, err 19 | } 20 | if value, ok := v.(IsVNCResponse); ok { 21 | return value, nil 22 | } 23 | 24 | return IsVNCResponse{}, errors.New("could not convert cached result") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/keys/key.go: -------------------------------------------------------------------------------- 1 | // keys package contains the public key for verifying digital signature of templates 2 | package keys 3 | 4 | import _ "embed" 5 | 6 | const PDVerifier = "projectdiscovery/nuclei-templates" 7 | 8 | //go:embed nuclei.crt 9 | var NucleiCert []byte // public key for verifying digital signature of templates 10 | -------------------------------------------------------------------------------- /pkg/keys/nuclei.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN PD NUCLEI USER CERTIFICATE----- 2 | MIIBgDCCASWgAwIBAgIEZSUZ3jAKBggqhkjOPQQDAjAsMSowKAYDVQQDEyFwcm9q 3 | ZWN0ZGlzY292ZXJ5L251Y2xlaS10ZW1wbGF0ZXMwHhcNMjMxMDEwMDkzMTEwWhcN 4 | MjcxMDA5MDkzMTEwWjAsMSowKAYDVQQDEyFwcm9qZWN0ZGlzY292ZXJ5L251Y2xl 5 | aS10ZW1wbGF0ZXMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASTaiE41H7LWudF 6 | SMCfnqguQMwEte7dz/FRfK2lmezE02w+I2VwcS3j5cPwNaqYRAJkQhk6+7li0GpG 7 | 9fb11Fs2ozUwMzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEw 8 | DAYDVR0TAQH/BAIwADAKBggqhkjOPQQDAgNJADBGAiEAhFsWwLDcWks3RUv3ujCs 9 | 4V1reu6KL+kELrCCQWu5FiUCIQDZbtqL30GPGYaPSpVmd6BKrZDBOfUVBsoCS7pS 10 | q3JLHQ== 11 | -----END PD NUCLEI USER CERTIFICATE----- -------------------------------------------------------------------------------- /pkg/loader/parser/parser.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/catalog" 5 | ) 6 | 7 | type Parser interface { 8 | LoadTemplate(templatePath string, tagFilter any, extraTags []string, catalog catalog.Catalog) (bool, error) 9 | ParseTemplate(templatePath string, catalog catalog.Catalog) (any, error) 10 | LoadWorkflow(templatePath string, catalog catalog.Catalog) (bool, error) 11 | } 12 | -------------------------------------------------------------------------------- /pkg/model/types/stringslice/stringslice_raw.go: -------------------------------------------------------------------------------- 1 | package stringslice 2 | 3 | type RawStringSlice struct { 4 | StringSlice 5 | } 6 | 7 | func NewRawStringSlice(value interface{}) *RawStringSlice { 8 | return &RawStringSlice{StringSlice: StringSlice{Value: value}} 9 | } 10 | 11 | func (rawStringSlice *RawStringSlice) Normalize(value string) string { 12 | return value 13 | } 14 | 15 | func (rawStringSlice *RawStringSlice) UnmarshalYAML(unmarshal func(interface{}) error) error { 16 | marshalledSlice, err := marshalStringToSlice(unmarshal) 17 | if err != nil { 18 | return err 19 | } 20 | rawStringSlice.Value = marshalledSlice 21 | return nil 22 | } 23 | 24 | func (rawStringSlice RawStringSlice) JSONSchemaAlias() any { 25 | return StringOrSlice("") 26 | } 27 | -------------------------------------------------------------------------------- /pkg/model/worflow_loader.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | // TODO shouldn't this rather be TemplateLoader? 4 | 5 | // WorkflowLoader is a loader interface required for workflow initialization. 6 | type WorkflowLoader interface { 7 | // GetTemplatePathsByTags returns a list of template paths based on the provided tags from the templates directory 8 | GetTemplatePathsByTags(tags []string) []string 9 | 10 | // GetTemplatePaths takes a list of templates and returns paths for them 11 | GetTemplatePaths(templatesList []string, noValidate bool) []string 12 | } 13 | -------------------------------------------------------------------------------- /pkg/operators/extractors/doc.go: -------------------------------------------------------------------------------- 1 | // Package extractors implements extractors for http response 2 | // data retrieval. 3 | package extractors 4 | -------------------------------------------------------------------------------- /pkg/operators/extractors/util.go: -------------------------------------------------------------------------------- 1 | package extractors 2 | 3 | // SupportsMap determines if the extractor type requires a map 4 | func SupportsMap(extractor *Extractor) bool { 5 | return extractor.Type.ExtractorType == KValExtractor || extractor.Type.ExtractorType == DSLExtractor 6 | } 7 | -------------------------------------------------------------------------------- /pkg/operators/matchers/doc.go: -------------------------------------------------------------------------------- 1 | // Package matchers implements matchers for http response 2 | // matching with templates. 3 | package matchers 4 | -------------------------------------------------------------------------------- /pkg/output/doc.go: -------------------------------------------------------------------------------- 1 | // Package output implements output writing interfaces for nuclei. 2 | package output 3 | -------------------------------------------------------------------------------- /pkg/output/format_json.go: -------------------------------------------------------------------------------- 1 | package output 2 | 3 | import ( 4 | jsoniter "github.com/json-iterator/go" 5 | ) 6 | 7 | // formatJSON formats the output for json based formatting 8 | func (w *StandardWriter) formatJSON(output *ResultEvent) ([]byte, error) { 9 | if !w.jsonReqResp { // don't show request-response in json if not asked 10 | output.Request = "" 11 | output.Response = "" 12 | } 13 | return jsoniter.Marshal(output) 14 | } 15 | -------------------------------------------------------------------------------- /pkg/progress/doc.go: -------------------------------------------------------------------------------- 1 | // Package progress implements progress display mechanism with very 2 | // simple command line statistics printing on runtime. 3 | package progress 4 | -------------------------------------------------------------------------------- /pkg/protocols/common/automaticscan/automaticscan_test.go: -------------------------------------------------------------------------------- 1 | package automaticscan 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestNormalizeAppName(t *testing.T) { 10 | appName := normalizeAppName("JBoss") 11 | require.Equal(t, "jboss", appName, "could not get normalized name") 12 | 13 | appName = normalizeAppName("JBoss:2.3.5") 14 | require.Equal(t, "jboss", appName, "could not get normalized name") 15 | } 16 | -------------------------------------------------------------------------------- /pkg/protocols/common/automaticscan/doc.go: -------------------------------------------------------------------------------- 1 | // Package automaticscan implements automatic technology based template 2 | // execution for a nuclei instance. 3 | // 4 | // First wappalyzer based technology detection is performed and templates 5 | // are executed based on the results found. The results of wappalyzer 6 | // technology detection are lowercased and split on space characters in the name, 7 | // which are then used as tags for the execution of the templates. 8 | // 9 | // Example - 10 | // 11 | // "Amazon Web Services,Jenkins,Atlassian Jira" -> "amazon,web,services,jenkins,atlassian,jira". 12 | // 13 | // Wappalyzergo (https://github.com/projectdiscovery/wappalyzergo) is used for wappalyzer tech 14 | // detection. 15 | // 16 | // The logic is very simple and can be further improved to increase the coverage of 17 | // this mode of nuclei execution. 18 | package automaticscan 19 | -------------------------------------------------------------------------------- /pkg/protocols/common/contextargs/doc.go: -------------------------------------------------------------------------------- 1 | // Package contextargs implements a generic entity for shared context within workflows 2 | // 3 | // All templates within a workflow shares the same cookiejar and a key-value store with shared items 4 | package contextargs 5 | -------------------------------------------------------------------------------- /pkg/protocols/common/contextargs/variables.go: -------------------------------------------------------------------------------- 1 | package contextargs 2 | 3 | // GenerateVariables from context args 4 | func GenerateVariables(ctx *Context) map[string]interface{} { 5 | vars := map[string]interface{}{ 6 | "ip": ctx.MetaInput.CustomIP, 7 | } 8 | return vars 9 | } 10 | -------------------------------------------------------------------------------- /pkg/protocols/common/expressions/variables_test.go: -------------------------------------------------------------------------------- 1 | package expressions 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestUnresolvedVariablesCheck(t *testing.T) { 11 | tests := []struct { 12 | data string 13 | err error 14 | }{ 15 | {"{{test}}", errors.New("unresolved variables found: test")}, 16 | {"{{test}}/{{another}}", errors.New("unresolved variables found: test,another")}, 17 | {"test", nil}, 18 | {"%7b%7btest%7d%7d", errors.New("unresolved variables found: test")}, 19 | {"%7B%7Bfirst%2Asecond%7D%7D", errors.New("unresolved variables found: first%2Asecond")}, 20 | {"{{7*7}}", nil}, 21 | {"{{'a'+'b'}}", nil}, 22 | {"{{'a'}}", nil}, 23 | } 24 | for _, test := range tests { 25 | err := ContainsUnresolvedVariables(test.data) 26 | require.Equal(t, test.err, err, "could not get unresolved variables") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /pkg/protocols/common/generators/env.go: -------------------------------------------------------------------------------- 1 | package generators 2 | 3 | import ( 4 | "os" 5 | 6 | stringsutil "github.com/projectdiscovery/utils/strings" 7 | ) 8 | 9 | var envVars map[string]interface{} 10 | 11 | func parseEnvVars() map[string]interface{} { 12 | sliceEnvVars := os.Environ() 13 | parsedEnvVars := make(map[string]interface{}, len(sliceEnvVars)) 14 | for _, envVar := range sliceEnvVars { 15 | key, _ := stringsutil.Before(envVar, "=") 16 | val, _ := stringsutil.After(envVar, "=") 17 | parsedEnvVars[key] = val 18 | } 19 | return parsedEnvVars 20 | } 21 | 22 | // EnvVars returns a map with all environment variables into a map 23 | func EnvVars() map[string]interface{} { 24 | if envVars == nil { 25 | envVars = parseEnvVars() 26 | } 27 | 28 | return envVars 29 | } 30 | -------------------------------------------------------------------------------- /pkg/protocols/common/generators/maps_test.go: -------------------------------------------------------------------------------- 1 | package generators 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestMergeMapsMany(t *testing.T) { 10 | got := MergeMapsMany(map[string]interface{}{"a": []string{"1", "2"}, "c": "5"}, map[string][]string{"b": {"3", "4"}}) 11 | require.Equal(t, map[string][]string{ 12 | "a": {"1", "2"}, 13 | "b": {"3", "4"}, 14 | "c": {"5"}, 15 | }, got, "could not get correct merged map") 16 | } 17 | -------------------------------------------------------------------------------- /pkg/protocols/common/generators/options.go: -------------------------------------------------------------------------------- 1 | package generators 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/types" 5 | ) 6 | 7 | // BuildPayloadFromOptions returns a map with the payloads provided via CLI 8 | func BuildPayloadFromOptions(options *types.Options) map[string]interface{} { 9 | m := make(map[string]interface{}) 10 | // merge with vars 11 | if !options.Vars.IsEmpty() { 12 | m = MergeMaps(m, options.Vars.AsMap()) 13 | } 14 | 15 | // merge with env vars 16 | if options.EnvironmentVariables { 17 | m = MergeMaps(EnvVars(), m) 18 | } 19 | return m 20 | } 21 | -------------------------------------------------------------------------------- /pkg/protocols/common/generators/slice.go: -------------------------------------------------------------------------------- 1 | package generators 2 | 3 | import stringsutil "github.com/projectdiscovery/utils/strings" 4 | 5 | // SliceToMap converts a slice of strings to map of string splitting each item at sep as "key sep value" 6 | func SliceToMap(s []string, sep string) map[string]interface{} { 7 | m := make(map[string]interface{}) 8 | for _, sliceItem := range s { 9 | key, _ := stringsutil.Before(sliceItem, sep) 10 | value, _ := stringsutil.After(sliceItem, sep) 11 | if key != "" { 12 | m[key] = value 13 | } 14 | } 15 | return m 16 | } 17 | -------------------------------------------------------------------------------- /pkg/protocols/common/helpers/deserialization/deserialization.go: -------------------------------------------------------------------------------- 1 | // Package deserialization implements helpers for deserialization issues in nuclei. 2 | package deserialization 3 | -------------------------------------------------------------------------------- /pkg/protocols/common/helpers/deserialization/helpers.go: -------------------------------------------------------------------------------- 1 | package deserialization 2 | 3 | import "bytes" 4 | 5 | func InsertInto(s string, interval int, sep rune) string { 6 | var buffer bytes.Buffer 7 | before := interval - 1 8 | last := len(s) - 1 9 | for i, char := range s { 10 | buffer.WriteRune(char) 11 | if i%interval == before && i != last { 12 | buffer.WriteRune(sep) 13 | } 14 | } 15 | buffer.WriteRune(sep) 16 | return buffer.String() 17 | } 18 | -------------------------------------------------------------------------------- /pkg/protocols/common/helpers/deserialization/testdata/Deserialize.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | class Deserialize { 4 | public static void main(String args[]) { 5 | FileInputStream fileIn = null; 6 | ObjectInputStream in = null; 7 | ValueObject vo2 = null; 8 | 9 | try { 10 | fileIn = new FileInputStream("ValueObject2.ser"); 11 | } 12 | catch(FileNotFoundException e) { 13 | e.printStackTrace(); 14 | } 15 | 16 | try { 17 | in = new ObjectInputStream(fileIn); 18 | } 19 | catch(IOException e) { 20 | e.printStackTrace(); 21 | } 22 | try { 23 | vo2 = (ValueObject) in.readObject(); 24 | } 25 | catch(Exception e) { 26 | e.printStackTrace(); 27 | } 28 | System.out.println(vo2); 29 | } 30 | } -------------------------------------------------------------------------------- /pkg/protocols/common/helpers/deserialization/testdata/README.md: -------------------------------------------------------------------------------- 1 | # testdata 2 | 3 | ### Test Unsafe Java Deserialization 4 | 5 | ``` 6 | javac Deserialize.java ValueObject.java 7 | # generate payload and write to ValueObject2.ser 8 | java Deserialize 9 | ``` 10 | 11 | Modified From: https://snyk.io/blog/serialization-and-deserialization-in-java/ -------------------------------------------------------------------------------- /pkg/protocols/common/helpers/deserialization/testdata/ValueObject.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | public class ValueObject implements Serializable { 4 | private String value; 5 | private String sideEffect; 6 | 7 | public ValueObject() { 8 | this("empty"); 9 | } 10 | 11 | public ValueObject(String value) { 12 | this.value = value; 13 | this.sideEffect = java.time.LocalTime.now().toString(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pkg/protocols/common/interactsh/const.go: -------------------------------------------------------------------------------- 1 | package interactsh 2 | 3 | import ( 4 | "errors" 5 | "regexp" 6 | "time" 7 | ) 8 | 9 | var ( 10 | defaultInteractionDuration = 60 * time.Second 11 | interactshURLMarkerRegex = regexp.MustCompile(`(%7[B|b]|\{){2}(interactsh-url(?:_[0-9]+){0,3})(%7[D|d]|\}){2}`) 12 | 13 | ErrInteractshClientNotInitialized = errors.New("interactsh client not initialized") 14 | ) 15 | 16 | const ( 17 | stopAtFirstMatchAttribute = "stop-at-first-match" 18 | templateIdAttribute = "template-id" 19 | 20 | defaultMaxInteractionsCount = 5000 21 | ) 22 | -------------------------------------------------------------------------------- /pkg/protocols/common/marker/marker.go: -------------------------------------------------------------------------------- 1 | package marker 2 | 3 | const ( 4 | // General marker (open/close) 5 | General = "§" 6 | // ParenthesisOpen marker - begin of a placeholder 7 | ParenthesisOpen = "{{" 8 | // ParenthesisClose marker - end of a placeholder 9 | ParenthesisClose = "}}" 10 | ) 11 | -------------------------------------------------------------------------------- /pkg/protocols/common/protocolstate/js.go: -------------------------------------------------------------------------------- 1 | package protocolstate 2 | 3 | import ( 4 | "github.com/dop251/goja" 5 | "github.com/dop251/goja/parser" 6 | "github.com/projectdiscovery/gologger" 7 | ) 8 | 9 | // NewJSRuntime returns a new javascript runtime 10 | // with defaults set 11 | // i.e sourcemap parsing is disabled by default 12 | func NewJSRuntime() *goja.Runtime { 13 | vm := goja.New() 14 | vm.SetParserOptions(parser.WithDisableSourceMaps) 15 | // disable eval by default 16 | if err := vm.Set("eval", "undefined"); err != nil { 17 | gologger.Error().Msgf("could not set eval to undefined: %s", err) 18 | } 19 | return vm 20 | } 21 | -------------------------------------------------------------------------------- /pkg/protocols/common/protocolstate/memoizer.go: -------------------------------------------------------------------------------- 1 | package protocolstate 2 | 3 | import ( 4 | "github.com/projectdiscovery/utils/memoize" 5 | ) 6 | 7 | var Memoizer *memoize.Memoizer 8 | 9 | func init() { 10 | var err error 11 | Memoizer, err = memoize.New(memoize.WithMaxSize(1500)) 12 | if err != nil { 13 | panic(err) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pkg/protocols/common/utils/excludematchers/excludematchers_test.go: -------------------------------------------------------------------------------- 1 | package excludematchers 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestExcludeMatchers(t *testing.T) { 10 | em := New([]string{"test-template:test-matcher", "new-template:*", "*:new-matcher", "only-template-id"}) 11 | 12 | require.True(t, em.Match("test-template", "test-matcher"), "could not get template-matcher value") 13 | require.False(t, em.Match("test-template", "random-matcher"), "could get template-matcher value") 14 | 15 | require.True(t, em.Match("new-template", "random-matcher"), "could not get template-matcher value wildcard") 16 | require.True(t, em.Match("random-template", "new-matcher"), "could not get template-matcher value wildcard") 17 | 18 | require.True(t, em.Match("only-template-id", "test"), "could not get only template id match value") 19 | } 20 | -------------------------------------------------------------------------------- /pkg/protocols/common/utils/vardump/vars.go: -------------------------------------------------------------------------------- 1 | package vardump 2 | 3 | var ( 4 | // EnableVarDump enables var dump for debugging optionally 5 | EnableVarDump bool 6 | // Limit is the maximum characters to be dumped 7 | Limit int = 255 8 | ) 9 | -------------------------------------------------------------------------------- /pkg/protocols/dns/cluster.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/cespare/xxhash" 7 | ) 8 | 9 | 10 | // TmplClusterKey generates a unique key for the request 11 | // to be used in the clustering process. 12 | func (request *Request) TmplClusterKey() uint64 { 13 | recursion := "" 14 | if request.Recursion != nil { 15 | recursion = fmt.Sprintf("%t", *request.Recursion) 16 | } 17 | inp := fmt.Sprintf("%s-%d-%d-%d-%s", request.Name, request.class, request.Retries, request.question, recursion) 18 | return xxhash.Sum64String(inp) 19 | } 20 | 21 | // IsClusterable returns true if the request is eligible to be clustered. 22 | func (request *Request) IsClusterable() bool { 23 | return !(len(request.Resolvers) > 0 || request.Trace || request.ID != "") 24 | } 25 | -------------------------------------------------------------------------------- /pkg/protocols/headless/engine/util.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions" 5 | "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/marker" 6 | "github.com/valyala/fasttemplate" 7 | ) 8 | 9 | // replaceWithValues replaces the template markers with the values 10 | // 11 | // Deprecated: Not used anymore. 12 | // nolint: unused 13 | func replaceWithValues(data string, values map[string]interface{}) string { 14 | return fasttemplate.ExecuteStringStd(data, marker.ParenthesisOpen, marker.ParenthesisClose, values) 15 | } 16 | 17 | func getExpressions(data string, values map[string]interface{}) []string { 18 | return expressions.FindExpressions(data, marker.ParenthesisOpen, marker.ParenthesisClose, values) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/protocols/headless/operators_test.go: -------------------------------------------------------------------------------- 1 | package headless 2 | -------------------------------------------------------------------------------- /pkg/protocols/http/cluster.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/cespare/xxhash" 8 | "github.com/projectdiscovery/nuclei/v3/pkg/utils" 9 | ) 10 | 11 | // TmplClusterKey generates a unique key for the request 12 | // to be used in the clustering process. 13 | func (request *Request) TmplClusterKey() uint64 { 14 | inp := fmt.Sprintf("%s-%d-%t-%t-%s-%d", request.Method.String(), request.MaxRedirects, request.DisableCookie, request.Redirects, strings.Join(request.Path, "-"), utils.MapHash(request.Headers)) 15 | return xxhash.Sum64String(inp) 16 | } 17 | 18 | // IsClusterable returns true if the request is eligible to be clustered. 19 | func (request *Request) IsClusterable() bool { 20 | return !(len(request.Payloads) > 0 || len(request.Fuzzing) > 0 || len(request.Raw) > 0 || len(request.Body) > 0 || request.Unsafe || request.NeedsRequestCondition() || request.Name != "") 21 | } 22 | -------------------------------------------------------------------------------- /pkg/protocols/http/cluster_test.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestCanCluster(t *testing.T) { 10 | req := &Request{Unsafe: true} 11 | require.False(t, req.IsClusterable(), "could cluster unsafe request") 12 | 13 | req = &Request{Path: []string{"{{BaseURL}}"}, Method: HTTPMethodTypeHolder{MethodType: HTTPGet}} 14 | newReq := &Request{Path: []string{"{{BaseURL}}"}, Method: HTTPMethodTypeHolder{MethodType: HTTPGet}} 15 | require.True(t, req.IsClusterable(), "could not cluster GET request") 16 | require.True(t, req.IsClusterable(), "could not cluster GET request") 17 | require.Equal(t, req.TmplClusterKey(), newReq.TmplClusterKey(), "cluster keys should be equal") 18 | } 19 | -------------------------------------------------------------------------------- /pkg/protocols/http/httpclientpool/errors.go: -------------------------------------------------------------------------------- 1 | package httpclientpool 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrRebuildURL = errors.New("could not rebuild request URL") 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/protocols/http/httputils/misc.go: -------------------------------------------------------------------------------- 1 | package httputils 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/projectdiscovery/nuclei/v3/pkg/types" 7 | mapsutil "github.com/projectdiscovery/utils/maps" 8 | ) 9 | 10 | // if template contains more than 1 request and matchers require requestcondition from 11 | // both requests , then we need to request for event from interactsh even if current request 12 | // doesnot use interactsh url in it 13 | func GetInteractshURLSFromEvent(event map[string]interface{}) []string { 14 | interactshUrls := map[string]struct{}{} 15 | for k, v := range event { 16 | if strings.HasPrefix(k, "interactsh-url") { 17 | interactshUrls[types.ToString(v)] = struct{}{} 18 | } 19 | } 20 | return mapsutil.GetKeys(interactshUrls) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/protocols/http/raw/doc.go: -------------------------------------------------------------------------------- 1 | // Package raw provides raw http request parsing abilities for nuclei. 2 | package raw 3 | -------------------------------------------------------------------------------- /pkg/protocols/http/validate.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import "github.com/pkg/errors" 4 | 5 | func (request *Request) validate() error { 6 | if request.Race && request.NeedsRequestCondition() { 7 | return errors.New("'race' and 'req-condition' can't be used together") 8 | } 9 | 10 | if request.Redirects && request.HostRedirects { 11 | return errors.New("'redirects' and 'host-redirects' can't be used together") 12 | } 13 | 14 | return nil 15 | } 16 | -------------------------------------------------------------------------------- /pkg/protocols/javascript/testcases/ms-sql-detect.yaml: -------------------------------------------------------------------------------- 1 | id: ms-sql-detect 2 | 3 | info: 4 | name: microsoft sql server(mssql) detection 5 | author: Ice3man543,tarunKoyalwar 6 | severity: info 7 | description: | 8 | ms sql detection template 9 | metadata: 10 | shodan-query: "port:1433" 11 | 12 | javascript: 13 | - code: | 14 | var m = require("nuclei/mssql"); 15 | var c = m.MSSQLClient(); 16 | c.IsMssql(Host, Port); 17 | 18 | args: 19 | Host: "{{Host}}" 20 | Port: "1433" 21 | 22 | matchers: 23 | - type: dsl 24 | dsl: 25 | - "response == true" 26 | - "success == true" 27 | condition: and 28 | 29 | 30 | -------------------------------------------------------------------------------- /pkg/protocols/javascript/testcases/ssh-server-fingerprint.yaml: -------------------------------------------------------------------------------- 1 | id: ssh-server-fingerprint 2 | 3 | info: 4 | name: Fingerprint SSH Server Software 5 | author: Ice3man543,tarunKoyalwar 6 | severity: info 7 | 8 | 9 | javascript: 10 | - code: | 11 | var m = require("nuclei/ssh"); 12 | var c = m.SSHClient(); 13 | var response = c.ConnectSSHInfoMode(Host, Port); 14 | to_json(response); 15 | args: 16 | Host: "{{Host}}" 17 | Port: "22" 18 | 19 | extractors: 20 | - type: json 21 | name: server 22 | json: 23 | - '.ServerID.Raw' 24 | part: response 25 | -------------------------------------------------------------------------------- /pkg/protocols/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestCalculateContentLength(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | expected int64 13 | contentLengthHeader int64 14 | bodyLength int64 15 | }{ 16 | {"content-length-header", 10, 10, 10}, 17 | {"content-length-header-with-body-length", 10, 10, 1000}, 18 | {"no-content-length-header-with-body-length", 1000, -1, 1000}, 19 | {"content-length-header-without-body-length", 10, 10, -1}, 20 | } 21 | for _, test := range tests { 22 | t.Run(test.name, func(t *testing.T) { 23 | got := CalculateContentLength(test.contentLengthHeader, test.bodyLength) 24 | require.Equal(t, test.expected, got) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /pkg/reporting/client.go: -------------------------------------------------------------------------------- 1 | package reporting 2 | 3 | import ( 4 | "github.com/projectdiscovery/nuclei/v3/pkg/output" 5 | ) 6 | 7 | // Client is a client for nuclei issue tracking module 8 | type Client interface { 9 | RegisterTracker(tracker Tracker) 10 | RegisterExporter(exporter Exporter) 11 | Close() 12 | Clear() 13 | CreateIssue(event *output.ResultEvent) error 14 | CloseIssue(event *output.ResultEvent) error 15 | GetReportingOptions() *Options 16 | } 17 | -------------------------------------------------------------------------------- /pkg/reporting/format/format.go: -------------------------------------------------------------------------------- 1 | package format 2 | 3 | type ResultFormatter interface { 4 | MakeBold(text string) string 5 | CreateCodeBlock(title string, content string, language string) string 6 | CreateTable(headers []string, rows [][]string) (string, error) 7 | CreateLink(title string, url string) string 8 | CreateHorizontalLine() string 9 | } 10 | -------------------------------------------------------------------------------- /pkg/scan/events/scan_noop.go: -------------------------------------------------------------------------------- 1 | //go:build !stats 2 | // +build !stats 3 | 4 | package events 5 | 6 | // AddScanEvent is a no-op function 7 | func AddScanEvent(event ScanEvent) { 8 | } 9 | 10 | func InitWithConfig(config *ScanConfig, statsDirectory string) { 11 | } 12 | 13 | func Close() { 14 | } 15 | -------------------------------------------------------------------------------- /pkg/templates/cache_test.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestCache(t *testing.T) { 11 | templates := NewCache() 12 | testErr := errors.New("test error") 13 | 14 | data, _, err := templates.Has("test") 15 | require.Nil(t, err, "invalid value for err") 16 | require.Nil(t, data, "invalid value for data") 17 | 18 | item := &Template{} 19 | 20 | templates.Store("test", item, nil, testErr) 21 | data, _, err = templates.Has("test") 22 | require.Equal(t, testErr, err, "invalid value for err") 23 | require.Equal(t, item, data, "invalid value for data") 24 | } 25 | -------------------------------------------------------------------------------- /pkg/templates/doc.go: -------------------------------------------------------------------------------- 1 | // Package templates contains the parser for a template for the engine. 2 | package templates 3 | -------------------------------------------------------------------------------- /pkg/templates/extensions/extensions.go: -------------------------------------------------------------------------------- 1 | package extensions 2 | 3 | const ( 4 | JSON = ".json" 5 | YAML = ".yaml" 6 | YML = ".yml" 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/templates/log_test.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func Test_appendAtSignToAuthors(t *testing.T) { 10 | result := appendAtSignToAuthors([]string{"user1", "user2", "user3"}) 11 | require.Equal(t, result, "@user1,@user2,@user3") 12 | } 13 | 14 | func Test_appendAtSignToMissingAuthors(t *testing.T) { 15 | result := appendAtSignToAuthors([]string{}) 16 | require.Equal(t, result, "@none") 17 | 18 | result = appendAtSignToAuthors(nil) 19 | require.Equal(t, result, "@none") 20 | } 21 | 22 | func Test_appendAtSignToOneAuthor(t *testing.T) { 23 | result := appendAtSignToAuthors([]string{"user1"}) 24 | require.Equal(t, result, "@user1") 25 | } 26 | -------------------------------------------------------------------------------- /pkg/templates/parser_config.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import "regexp" 4 | 5 | var ( 6 | ReTemplateID = regexp.MustCompile(`^([a-zA-Z0-9]+[-_])*[a-zA-Z0-9]+$`) 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/templates/parser_error.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | errorutil "github.com/projectdiscovery/utils/errors" 5 | ) 6 | 7 | var ( 8 | ErrMandatoryFieldMissingFmt = errorutil.NewWithFmt("mandatory '%s' field is missing") 9 | ErrInvalidField = errorutil.NewWithFmt("invalid field format for '%s' (allowed format is %s)") 10 | ErrWarningFieldMissing = errorutil.NewWithFmt("field '%s' is missing") 11 | ErrCouldNotLoadTemplate = errorutil.NewWithFmt("Could not load template %s: %s") 12 | ErrLoadedWithWarnings = errorutil.NewWithFmt("Loaded template %s: with syntax warning : %s") 13 | ) 14 | -------------------------------------------------------------------------------- /pkg/templates/parser_stats.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | const ( 4 | SyntaxWarningStats = "syntax-warnings" 5 | SyntaxErrorStats = "syntax-errors" 6 | RuntimeWarningsStats = "runtime-warnings" 7 | SkippedCodeTmplTamperedStats = "unsigned-warnings" 8 | ExcludedHeadlessTmplStats = "headless-flag-missing-warnings" 9 | TemplatesExcludedStats = "templates-executed" 10 | ExcludedCodeTmplStats = "code-flag-missing-warnings" 11 | ExludedDastTmplStats = "fuzz-flag-missing-warnings" 12 | SkippedUnsignedStats = "skipped-unsigned-stats" // tracks loading of unsigned templates 13 | ExcludedSelfContainedStats = "excluded-self-contained-stats" 14 | ExcludedFileStats = "excluded-file-stats" 15 | SkippedRequestSignatureStats = "skipped-request-signature-stats" 16 | ) 17 | -------------------------------------------------------------------------------- /pkg/templates/signer/.nuclei-config/nuclei/.templates-config.json: -------------------------------------------------------------------------------- 1 | {"nuclei-templates-directory":"/Users/tarun/nuclei-templates","custom-s3-templates-directory":"/Users/tarun/nuclei-templates/s3","custom-github-templates-directory":"/Users/tarun/nuclei-templates/github","custom-gitlab-templates-directory":"/Users/tarun/nuclei-templates/gitlab","custom-azure-templates-directory":"/Users/tarun/nuclei-templates/azure","nuclei-latest-version":"","nuclei-templates-latest-version":""} -------------------------------------------------------------------------------- /pkg/templates/tests/json-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "go-integration-test", 3 | "info": { 4 | "name": "Basic Go Integration Test", 5 | "author": "pdteam", 6 | "severity": "info" 7 | }, 8 | "requests": [ 9 | { 10 | "method": "GET", 11 | "path": [ 12 | "{{BaseURL}}" 13 | ], 14 | "headers": { 15 | "test": "nuclei" 16 | }, 17 | "matchers": [ 18 | { 19 | "type": "word", 20 | "words": [ 21 | "This is test headers matcher text" 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /pkg/templates/tests/match-1.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | requests: 9 | - method: GET 10 | path: 11 | - "{{BaseURL}}" 12 | matchers: 13 | - type: word 14 | words: 15 | - "This is test matcher text" 16 | -------------------------------------------------------------------------------- /pkg/templates/tests/multiproto.yaml: -------------------------------------------------------------------------------- 1 | id: nuclei-multi-protocol 2 | 3 | info: 4 | name: multi protocol support 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" # dns request 10 | type: cname 11 | 12 | ssl: 13 | - address: "{{Hostname}}" # ssl request 14 | 15 | http: 16 | - method: GET 17 | path: 18 | - "{{BaseURL}}" # http request 19 | 20 | headers: 21 | Host: "{{ssl_subject_cn}}" # host extracted from ssl request 22 | Metadata: "{{ssl_cipher}}" 23 | 24 | matchers: 25 | - type: dsl 26 | dsl: 27 | # - contains(http_body,'File not found') # check for http string 28 | - http_status_code == 404 29 | - contains(dns_cname, 'github.io') # check for cname 30 | condition: and -------------------------------------------------------------------------------- /pkg/templates/tests/no-author.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get 2 | 3 | info: 4 | name: Basic GET Request 5 | severity: info 6 | 7 | requests: 8 | - method: GET 9 | path: 10 | - "{{BaseURL}}" 11 | matchers: 12 | - type: word 13 | words: 14 | - "This is test matcher text" 15 | -------------------------------------------------------------------------------- /pkg/templates/tests/no-req.yaml: -------------------------------------------------------------------------------- 1 | id: basic-get 2 | 3 | info: 4 | name: Basic GET Request 5 | author: pdteam 6 | severity: info 7 | 8 | requests: 9 | 10 | -------------------------------------------------------------------------------- /pkg/templates/tests/workflow-invalid.yaml: -------------------------------------------------------------------------------- 1 | id: workflow-example 2 | 3 | info: 4 | name: Test Invalid Workflow Template 5 | author: pdteam 6 | severity: info 7 | 8 | http: 9 | - raw: 10 | - | 11 | POST /re HTTP/1.1 12 | Host: {{Hostname}} 13 | 14 | {{code_response}} 15 | 16 | workflows: 17 | - template: tests/match-1.yaml 18 | - template: tests/match-1.yaml 19 | -------------------------------------------------------------------------------- /pkg/templates/tests/workflow.yaml: -------------------------------------------------------------------------------- 1 | id: workflow-example 2 | 3 | info: 4 | name: Test Workflow Template 5 | author: pdteam 6 | severity: info 7 | 8 | workflows: 9 | - template: tests/match-1.yaml 10 | - template: tests/match-1.yaml 11 | -------------------------------------------------------------------------------- /pkg/testutils/testheadless/headless_local.go: -------------------------------------------------------------------------------- 1 | //go:build headless_local 2 | 3 | package testheadless 4 | 5 | // HeadlessLocal determines if local headless chrome should be used in tests 6 | const HeadlessLocal = true 7 | -------------------------------------------------------------------------------- /pkg/testutils/testheadless/headless_runtime.go: -------------------------------------------------------------------------------- 1 | //go:build !headless_local 2 | 3 | package testheadless 4 | 5 | // HeadlessLocal determines if local headless chrome should be used in tests 6 | const HeadlessLocal = false 7 | -------------------------------------------------------------------------------- /pkg/tmplexec/doc.go: -------------------------------------------------------------------------------- 1 | package tmplexec 2 | 3 | // tmplexec is package that provides 4 | // template executors it is one level higher than protocols 5 | // and deals with execution of entire template 6 | -------------------------------------------------------------------------------- /pkg/tmplexec/flow/doc.go: -------------------------------------------------------------------------------- 1 | package flow 2 | -------------------------------------------------------------------------------- /pkg/tmplexec/flow/testcases/condition-flow-extractors.yaml: -------------------------------------------------------------------------------- 1 | id: condition-flow-extractors 2 | info: 3 | name: Condition Flow Extractors 4 | author: pdteam 5 | severity: info 6 | 7 | flow: dns() && http() 8 | 9 | dns: 10 | - name: "{{FQDN}}" 11 | type: A 12 | 13 | extractors: 14 | - type: dsl 15 | name: a 16 | internal: true 17 | dsl: 18 | - a 19 | 20 | http: 21 | - method: GET 22 | path: 23 | - "{{BaseURL}}/?ref={{a}}" 24 | 25 | matchers: 26 | - type: word 27 | words: 28 | - "ok" -------------------------------------------------------------------------------- /pkg/tmplexec/flow/testcases/condition-flow-no-operators.yaml: -------------------------------------------------------------------------------- 1 | id: condition-flow-no-operators 2 | info: 3 | name: Condition Flow No Operators 4 | author: pdteam 5 | severity: info 6 | 7 | flow: dns() && http() 8 | 9 | dns: 10 | - name: "{{FQDN}}" 11 | type: CNAME 12 | 13 | http: 14 | - method: GET 15 | path: 16 | - "{{BaseURL}}/?ref={{dns_cname}}" 17 | 18 | matchers: 19 | - type: word 20 | words: 21 | - "html>" -------------------------------------------------------------------------------- /pkg/tmplexec/flow/testcases/condition-flow.yaml: -------------------------------------------------------------------------------- 1 | id: vercel-hosted-detection 2 | info: 3 | name: Vercel-hosted detection 4 | author: pdteam 5 | severity: info 6 | 7 | 8 | flow: dns() && http() 9 | 10 | dns: 11 | - name: "{{FQDN}}" 12 | type: CNAME 13 | 14 | matchers: 15 | - type: word 16 | words: 17 | - "vercel-dns" 18 | 19 | http: 20 | - method: GET 21 | path: 22 | - "{{dns_cname}}" 23 | 24 | matchers: 25 | - type: word 26 | words: 27 | - "DEPLOYMENT_NOT_FOUND" -------------------------------------------------------------------------------- /pkg/tmplexec/flow/testcases/nuclei-flow-dns.yaml: -------------------------------------------------------------------------------- 1 | id: nuclei-flow-dns 2 | 3 | info: 4 | name: Nuclei flow dns 5 | author: pdteam 6 | severity: info 7 | description: Description of the Template 8 | reference: https://example-reference-link 9 | 10 | flow: | 11 | dns(1); 12 | template["nameservers"].forEach(nameserver => { 13 | set("nameserver",nameserver); 14 | dns(2); 15 | }); 16 | 17 | dns: 18 | - name: "{{FQDN}}" 19 | type: NS 20 | matchers: 21 | - type: word 22 | words: 23 | - "IN\tNS" 24 | extractors: 25 | - type: regex 26 | internal: true 27 | name: "nameservers" 28 | group: 1 29 | regex: 30 | - "IN\tNS\t(.+)" 31 | 32 | - name: "{{nameserver}}" 33 | type: A 34 | class: inet 35 | retries: 3 36 | recursion: true 37 | extractors: 38 | - type: dsl 39 | dsl: 40 | - "a" -------------------------------------------------------------------------------- /pkg/tmplexec/flow/util.go: -------------------------------------------------------------------------------- 1 | package flow 2 | 3 | import "github.com/projectdiscovery/nuclei/v3/pkg/operators" 4 | 5 | // Checks if template has matchers 6 | func hasMatchers(all []*operators.Operators) bool { 7 | for _, operator := range all { 8 | if len(operator.Matchers) > 0 { 9 | return true 10 | } 11 | } 12 | return false 13 | } 14 | 15 | // hasOperators checks if template has operators (i.e matchers/extractors) 16 | func hasOperators(all []*operators.Operators) bool { 17 | for _, operator := range all { 18 | if operator != nil { 19 | return true 20 | } 21 | } 22 | return false 23 | } 24 | 25 | func flatten(v interface{}) interface{} { 26 | switch v := v.(type) { 27 | case []interface{}: 28 | if len(v) == 1 { 29 | return v[0] 30 | } 31 | return v 32 | case []string: 33 | if len(v) == 1 { 34 | return v[0] 35 | } 36 | return v 37 | default: 38 | return v 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /pkg/tmplexec/multiproto/doc.go: -------------------------------------------------------------------------------- 1 | package multiproto 2 | 3 | // multiproto is a template executer engine that executes multiple protocols 4 | // with shared logic in between 5 | -------------------------------------------------------------------------------- /pkg/tmplexec/multiproto/testcases/multiprotodynamic.yaml: -------------------------------------------------------------------------------- 1 | id: dns-http-dynamic-values 2 | 3 | info: 4 | name: multi protocol request with dynamic values 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" # DNS Request 10 | type: a 11 | 12 | http: 13 | - method: GET # http request 14 | path: 15 | - "{{BaseURL}}" 16 | 17 | matchers: 18 | - type: dsl 19 | dsl: 20 | - body == "ok" 21 | - dns_a == '128.199.158.128' # check for A record (extracted information from dns response) 22 | condition: and -------------------------------------------------------------------------------- /pkg/tmplexec/multiproto/testcases/multiprotowithprefix.yaml: -------------------------------------------------------------------------------- 1 | id: dns-http-proto-prefix 2 | 3 | info: 4 | name: multi protocol request with dynamic values 5 | author: pdteam 6 | severity: info 7 | 8 | dns: 9 | - name: "{{FQDN}}" # DNS Request 10 | type: cname 11 | 12 | ssl: 13 | - address: "{{Hostname}}" # ssl request 14 | 15 | http: 16 | - method: GET # http request 17 | path: 18 | - "{{BaseURL}}" 19 | 20 | matchers: 21 | - type: dsl 22 | dsl: 23 | - contains(http_body, 'ProjectDiscovery') # check for http string 24 | - dns_cname == 'cname.vercel-dns.com' # check for cname (extracted information from dns response) 25 | - ssl_subject_cn == 'cloud.projectdiscovery.io' 26 | condition: and -------------------------------------------------------------------------------- /pkg/types/scanstrategy/scan_strategy.go: -------------------------------------------------------------------------------- 1 | package scanstrategy 2 | 3 | import ( 4 | mapsutil "github.com/projectdiscovery/utils/maps" 5 | ) 6 | 7 | // ScanStrategy supported 8 | type ScanStrategy uint8 9 | 10 | const ( 11 | Auto ScanStrategy = iota 12 | HostSpray 13 | TemplateSpray 14 | ) 15 | 16 | var strategies mapsutil.Map[ScanStrategy, string] 17 | 18 | func init() { 19 | strategies = make(mapsutil.Map[ScanStrategy, string]) 20 | strategies[Auto] = "auto" 21 | strategies[HostSpray] = "host-spray" 22 | strategies[TemplateSpray] = "template-spray" 23 | } 24 | 25 | // String representation of the scan strategy 26 | func (s ScanStrategy) String() string { 27 | return strategies[s] 28 | } 29 | -------------------------------------------------------------------------------- /pkg/utils/expand/expand.go: -------------------------------------------------------------------------------- 1 | package expand 2 | 3 | import ( 4 | "github.com/projectdiscovery/mapcidr" 5 | "github.com/projectdiscovery/mapcidr/asn" 6 | ) 7 | 8 | // Expands CIDR to IPs 9 | func CIDR(value string) []string { 10 | var ips []string 11 | ipsCh, _ := mapcidr.IPAddressesAsStream(value) 12 | for ip := range ipsCh { 13 | ips = append(ips, ip) 14 | } 15 | return ips 16 | } 17 | 18 | // Expand ASN to IPs 19 | func ASN(value string) []string { 20 | var ips []string 21 | cidrs, _ := asn.GetCIDRsForASNNum(value) 22 | for _, cidr := range cidrs { 23 | ips = append(ips, CIDR(cidr.String())...) 24 | } 25 | return ips 26 | } 27 | -------------------------------------------------------------------------------- /pkg/utils/index.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | // TransformIndex transforms user given index (start from 1) to array index (start from 0) 4 | // in safe way without panic i.e negative index or index out of range 5 | func TransformIndex[T any](arr []T, index int) int { 6 | if index <= 1 { 7 | // negative index 8 | return 0 9 | } 10 | if index >= len(arr) { 11 | // index out of range 12 | return len(arr) - 1 13 | } 14 | // valid index 15 | return index - 1 16 | } 17 | -------------------------------------------------------------------------------- /pkg/utils/insertion_ordered_map_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | "gopkg.in/yaml.v2" 8 | ) 9 | 10 | func TestUnmarshalInsertionOrderedMapYAML(t *testing.T) { 11 | var data = `a1: test 12 | a2: value 13 | a3: new` 14 | 15 | var value InsertionOrderedStringMap 16 | err := yaml.Unmarshal([]byte(data), &value) 17 | require.NoError(t, err, "could not unmarshal map") 18 | 19 | var items []string 20 | value.ForEach(func(key string, value interface{}) { 21 | items = append(items, key) 22 | }) 23 | require.Equal(t, []string{"a1", "a2", "a3"}, items, "could not get ordered keys") 24 | } 25 | -------------------------------------------------------------------------------- /pkg/utils/json/json.go: -------------------------------------------------------------------------------- 1 | //go:build !go1.24 && (linux || darwin || windows) && (amd64 || arm64) 2 | // +build !go1.24 3 | // +build linux darwin windows 4 | // +build amd64 arm64 5 | 6 | package json 7 | 8 | import "github.com/bytedance/sonic" 9 | 10 | var api = sonic.ConfigStd 11 | 12 | // Exported functions from the [sonic.API]. 13 | var ( 14 | Marshal = api.Marshal 15 | Unmarshal = api.Unmarshal 16 | MarshalIndent = api.MarshalIndent 17 | NewDecoder = api.NewDecoder 18 | NewEncoder = api.NewEncoder 19 | ) 20 | 21 | // Encoder is a JSON encoder. 22 | type Encoder = sonic.Encoder 23 | 24 | // Decoder is a JSON decoder. 25 | type Decoder = sonic.Decoder 26 | 27 | // SetConfig sets the configuration for the JSON package. 28 | func SetConfig(config *sonic.Config) { 29 | api = config.Froze() 30 | } 31 | -------------------------------------------------------------------------------- /pkg/utils/json/json_fallback.go: -------------------------------------------------------------------------------- 1 | //go:build go1.24 || !(linux || darwin || windows) || !(amd64 || arm64) 2 | // +build go1.24 !linux,!darwin,!windows !amd64,!arm64 3 | 4 | package json 5 | 6 | import "github.com/goccy/go-json" 7 | 8 | // Exported functions from the [json] package. 9 | var ( 10 | Marshal = json.Marshal 11 | Unmarshal = json.Unmarshal 12 | MarshalIndent = json.MarshalIndent 13 | NewDecoder = json.NewDecoder 14 | NewEncoder = json.NewEncoder 15 | ) 16 | 17 | // Encoder is a JSON encoder. 18 | type Encoder = json.Encoder 19 | 20 | // Decoder is a JSON decoder. 21 | type Decoder = json.Decoder 22 | -------------------------------------------------------------------------------- /pkg/utils/monitor/monitor_test.go: -------------------------------------------------------------------------------- 1 | package monitor 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestMonitorCompareStringSliceEqual(t *testing.T) { 10 | value := compareStringSliceEqual([]string{"a", "b"}, []string{"b", "a"}) 11 | require.True(t, value, "could not get correct value") 12 | 13 | value = compareStringSliceEqual([]string{"a", "c"}, []string{"b", "a"}) 14 | require.False(t, value, "could get incorrect value") 15 | } 16 | -------------------------------------------------------------------------------- /pkg/utils/stats/doc.go: -------------------------------------------------------------------------------- 1 | // Package stats provides a storage mechanism for storing 2 | // and display vital statistics of the engine at various durations. 3 | package stats 4 | -------------------------------------------------------------------------------- /pkg/utils/template_path.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" 7 | "github.com/projectdiscovery/nuclei/v3/pkg/keys" 8 | ) 9 | 10 | const ( 11 | // TemplatesRepoURL is the URL for files in nuclei-templates repository 12 | TemplatesRepoURL = "https://cloud.projectdiscovery.io/public/" 13 | ) 14 | 15 | // TemplatePathURL returns the Path and URL for the provided template 16 | func TemplatePathURL(fullPath, templateId, templateVerifier string) (path string, url string) { 17 | configData := config.DefaultConfig 18 | if configData.TemplatesDirectory != "" && strings.HasPrefix(fullPath, configData.TemplatesDirectory) { 19 | path = strings.TrimPrefix(strings.TrimPrefix(fullPath, configData.TemplatesDirectory), "/") 20 | } 21 | if templateVerifier == keys.PDVerifier { 22 | url = TemplatesRepoURL + templateId 23 | } 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /pkg/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestUnwrapError(t *testing.T) { 11 | require.Equal(t, nil, UnwrapError(nil)) 12 | 13 | errOne := fmt.Errorf("error one") 14 | require.Equal(t, errOne, UnwrapError(errOne)) 15 | 16 | errTwo := fmt.Errorf("error with error: %w", errOne) 17 | require.Equal(t, errOne, UnwrapError(errTwo)) 18 | 19 | errThree := fmt.Errorf("error with error: %w", errTwo) 20 | require.Equal(t, errOne, UnwrapError(errThree)) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/workflows/doc.go: -------------------------------------------------------------------------------- 1 | // Package workflows contains the workflows 2 | package workflows 3 | -------------------------------------------------------------------------------- /static/Join-Discord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/Join-Discord.png -------------------------------------------------------------------------------- /static/check-nuclei-documentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/check-nuclei-documentation.png -------------------------------------------------------------------------------- /static/learn-more-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/learn-more-button.png -------------------------------------------------------------------------------- /static/nuclei-cover-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-cover-image.png -------------------------------------------------------------------------------- /static/nuclei-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-cover.png -------------------------------------------------------------------------------- /static/nuclei-flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-flow.jpg -------------------------------------------------------------------------------- /static/nuclei-getting-started.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-getting-started.png -------------------------------------------------------------------------------- /static/nuclei-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-logo.png -------------------------------------------------------------------------------- /static/nuclei-template-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-template-example.png -------------------------------------------------------------------------------- /static/nuclei-templates-teamcity-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-templates-teamcity-example.png -------------------------------------------------------------------------------- /static/nuclei-templates-teamcity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-templates-teamcity.png -------------------------------------------------------------------------------- /static/nuclei-write-your-first-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/nuclei-write-your-first-template.png -------------------------------------------------------------------------------- /static/projectdiscovery-browse-results.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/projectdiscovery-browse-results.gif -------------------------------------------------------------------------------- /static/regression-cycle.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/regression-with-nuclei.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/regression-with-nuclei.jpg -------------------------------------------------------------------------------- /static/teamcity-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectdiscovery/nuclei/a4859df5e9c9e5476a8cd5f2e2d2e96566df2524/static/teamcity-example.png --------------------------------------------------------------------------------