Compare commits

..
Author SHA1 Message Date
Ice3man 53b167064a feat: loading templates performance improvements 2025-08-02 15:56:04 +05:30
poningandDwi Siswanto 078284936c fix(offlinehttp): Replace "-" in headers with "_" for DSL variables (#6363)
* Replace "-" in headers with "_" for DSL variables in passive mode

* test(offlinehttp): adjust haystack & needle in `TestHTTPOperatorExtract`

Signed-off-by: Dwi Siswanto <[email protected]>

---------

Signed-off-by: Dwi Siswanto <[email protected]>
Co-authored-by: Dwi Siswanto <[email protected]>
2025-08-02 15:56:04 +05:30
Štefan BaeblerandDwi Siswanto 434f6d32fc Bump github.com/bytedance/sonic to v1.14.0 for Go 1.25 compatibility (#6348)
* Bump github.com/bytedance/sonic to v1.14.0  for Go 1.25 compatibility

Fixes #6335
by using https://github.com/bytedance/sonic/releases/tag/v1.14.0

$ go get github.com/bytedance/[email protected].0 && go mod tidy
go: upgraded github.com/bytedance/sonic v1.13.3 => v1.14.0
go: upgraded github.com/bytedance/sonic/loader v0.2.4 => v0.3.0

* doc(json): update supported plats

Signed-off-by: Dwi Siswanto <[email protected]>

---------

Signed-off-by: Dwi Siswanto <[email protected]>
Co-authored-by: Dwi Siswanto <[email protected]>
2025-08-02 15:56:04 +05:30
jishudashen 0c510253d2 chore: fix inconsistent function name in comment
Signed-off-by: jishudashen <[email protected]>
2025-08-02 15:56:04 +05:30
Dwi Siswanto dfcc38adb7 feat(code): log unavail engines as an err while validating (#6326)
* feat(code): log unavail engines as an err while validating

Signed-off-by: Dwi Siswanto <[email protected]>

* chore(chore): i meant highest level

Signed-off-by: Dwi Siswanto <[email protected]>

---------

Signed-off-by: Dwi Siswanto <[email protected]>
2025-08-02 15:56:04 +05:30
3feb011459 Support concurrent Nuclei engines in the same process (#6322)
* support for concurrent nuclei engines

* clarify LfaAllowed race

* remove unused mutex

* update LfaAllowed logic to prevent races until it can be reworked for per-execution ID

* Update pkg/templates/parser.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* debug tests

* debug gh action

* fixig gh template test

* using atomic

* using synclockmap

* restore tests concurrency

* lint

* wiring executionId in js fs

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Mzack9999 <[email protected]>
2025-08-02 15:56:04 +05:30
HD Moore 3951816686 avoid data races using mutex for memguardian 2025-08-02 15:56:04 +05:30
HD Moore 84b84b6ade avoid data races by using request clones 2025-08-02 15:56:04 +05:30
gopherorg 9e040516f2 refactor: use maps.Copy for cleaner map handling (#6283)
Signed-off-by: gopherorg <[email protected]>
2025-08-02 15:56:04 +05:30
Dwi Siswanto 5cb038fb33 build(docker): bump builder image golang:1.23-alpine => golang:1.24-alpine (#6316)
Signed-off-by: Dwi Siswanto <[email protected]>
2025-08-02 15:56:04 +05:30
0c7bade615 Remove singletons from Nuclei engine (continuation of #6210) (#6296)
* introducing execution id

* wip

* .

* adding separate execution context id

* lint

* vet

* fixing pg dialers

* test ignore

* fixing loader FD limit

* test

* fd fix

* wip: remove CloseProcesses() from dev merge

* wip: fix merge issue

* protocolstate: stop memguarding on last dialer delete

* avoid data race in dialers.RawHTTPClient

* use shared logger and avoid race conditions

* use shared logger and avoid race conditions

* go mod

* patch executionId into compiled template cache

* clean up comment in Parse

* go mod update

* bump echarts

* address merge issues

* fix use of gologger

* switch cmd/nuclei to options.Logger

* address merge issues with go.mod

* go vet: address copy of lock with new Copy function

* fixing tests

* disable speed control

* fix nil ExecuterOptions

* removing deprecated code

* fixing result print

* default logger

* cli default logger

* filter warning from results

* fix performance test

* hardcoding path

* disable upload

* refactor(runner): uses `Warning` instead of `Print` for `pdcpUploadErrMsg`

Signed-off-by: Dwi Siswanto <[email protected]>

* Revert "disable upload"

This reverts commit 114fbe6663.

* Revert "hardcoding path"

This reverts commit cf12ca800e.

---------

Signed-off-by: Dwi Siswanto <[email protected]>
Co-authored-by: Mzack9999 <[email protected]>
Co-authored-by: Dwi Siswanto <[email protected]>
Co-authored-by: Dwi Siswanto <[email protected]>
2025-08-02 15:56:04 +05:30
Jose De La O Hernandez 1bafeca614 fixing panic caused by uninitialized colorizer (#6315) 2025-08-02 15:56:04 +05:30
Dwi Siswantoandcoderabbitai[bot] 3be2eb7cf2 fix(lib): scans didn't stop on ctx cancellation (#6310)
* fix(lib): scans didn't stop on ctx cancellation

Signed-off-by: Dwi Siswanto <[email protected]>

* Update lib/sdk_test.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(lib): wait resources to be released b4 return

Signed-off-by: Dwi Siswanto <[email protected]>

---------

Signed-off-by: Dwi Siswanto <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-08-02 15:56:04 +05:30
Dwi Siswanto 58d874f291 chore(config): rm deprecated codes and calls
Signed-off-by: Dwi Siswanto <[email protected]>
2025-08-02 15:56:04 +05:30
dependabot[bot] 9d0886d267 chore(deps): bump the modules group with 3 updates (#6305)
Bumps the modules group with 3 updates: [github.com/projectdiscovery/retryablehttp-go](https://github.com/projectdiscovery/retryablehttp-go), [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) and [github.com/projectdiscovery/cdncheck](https://github.com/projectdiscovery/cdncheck).


Updates `github.com/projectdiscovery/retryablehttp-go` from 1.0.116 to 1.0.117
- [Release notes](https://github.com/projectdiscovery/retryablehttp-go/releases)
- [Commits](https://github.com/projectdiscovery/retryablehttp-go/compare/v1.0.116...v1.0.117)

Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.35 to 0.2.36
- [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases)
- [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.35...v0.2.36)

Updates `github.com/projectdiscovery/cdncheck` from 1.1.15 to 1.1.26
- [Release notes](https://github.com/projectdiscovery/cdncheck/releases)
- [Changelog](https://github.com/projectdiscovery/cdncheck/blob/main/.goreleaser.yaml)
- [Commits](https://github.com/projectdiscovery/cdncheck/compare/v1.1.15...v1.1.26)

---
updated-dependencies:
- dependency-name: github.com/projectdiscovery/retryablehttp-go
  dependency-version: 1.0.117
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: modules
- dependency-name: github.com/projectdiscovery/wappalyzergo
  dependency-version: 0.2.36
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: modules
- dependency-name: github.com/projectdiscovery/cdncheck
  dependency-version: 1.1.26
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: modules
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-02 15:56:04 +05:30
Mzack9999 5094c0cf17 bumping version + memory cleanup 2025-08-02 15:56:04 +05:30
alban-stourbe-wmx aaf09431ff fix(headless): Variables are now available into headless template (#6301)
* fix(headless): variables now available into simple headless template

* chore: erase debug logs
2025-08-02 15:56:04 +05:30
83 changed files with 439 additions and 955 deletions

No files matched your search

+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/golangci-lint/v2@v1
- uses: projectdiscovery/actions/golangci-lint@v1
tests:
name: "Tests"
+4 -13
View File
@@ -15,8 +15,8 @@ ifneq ($(shell go env GOOS),darwin)
endif
.PHONY: all build build-stats clean devtools-all devtools-bindgen devtools-scrapefuncs
.PHONY: devtools-tsgen docs docgen dsl-docs functional fuzzplayground go-build lint lint-strict syntax-docs
.PHONY: integration jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test test-with-lint
.PHONY: devtools-tsgen docs docgen dsl-docs functional fuzzplayground go-build syntax-docs
.PHONY: integration jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test
.PHONY: tidy ts verify download vet template-validate
all: build
@@ -146,14 +146,5 @@ dsl-docs:
template-validate: build
template-validate:
./bin/nuclei -ut
./bin/nuclei -validate \
-et .github/ \
-et helpers/payloads/ \
-et http/technologies \
-ept code
./bin/nuclei -validate \
-w workflows \
-et .github/ \
-et helpers/payloads/ \
-et http/technologies \
-ept code
./bin/nuclei -validate -et http/technologies
./bin/nuclei -validate -w workflows -et http/technologies
+9 -9
View File
@@ -19,7 +19,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
logutil "github.com/projectdiscovery/utils/log"
sliceutil "github.com/projectdiscovery/utils/slice"
stringsutil "github.com/projectdiscovery/utils/strings"
@@ -196,7 +196,7 @@ func (d *httpDefaultMatcherCondition) Execute(filePath string) error {
return err
}
if routerErr != nil {
return errkit.Append(errkit.New("failed to send http request to interactsh server"), routerErr)
return errorutil.NewWithErr(routerErr).Msgf("failed to send http request to interactsh server")
}
if err := expectResultsCount(results, 1); err != nil {
return err
@@ -628,10 +628,10 @@ func (h *httpRawWithParams) Execute(filePath string) error {
// we intentionally use params["test"] instead of params.Get("test") to test the case where
// there are multiple parameters with the same name
if !reflect.DeepEqual(params["key1"], []string{"value1"}) {
errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"value1"}, params["key1"])), errx)
errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value1"}, params["key1"])
}
if !reflect.DeepEqual(params["key2"], []string{"value2"}) {
errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"value2"}, params["key2"])), errx)
errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value2"}, params["key2"])
}
_, _ = fmt.Fprintf(w, "Test is test raw-params-matcher text")
})
@@ -971,10 +971,10 @@ func (h *httpRequestSelfContainedWithParams) Execute(filePath string) error {
// we intentionally use params["test"] instead of params.Get("test") to test the case where
// there are multiple parameters with the same name
if !reflect.DeepEqual(params["something"], []string{"here"}) {
errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"here"}, params["something"])), errx)
errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"here"}, params["something"])
}
if !reflect.DeepEqual(params["key"], []string{"value"}) {
errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"value"}, params["key"])), errx)
errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value"}, params["key"])
}
_, _ = w.Write([]byte("This is self-contained response"))
})
@@ -1027,10 +1027,10 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error {
// create temp file
FileLoc, err := os.CreateTemp("", "self-contained-payload-*.txt")
if err != nil {
return errkit.Append(errkit.New("failed to create temp file"), err)
return errorutil.NewWithErr(err).Msgf("failed to create temp file")
}
if _, err := FileLoc.Write([]byte("one\ntwo\n")); err != nil {
return errkit.Append(errkit.New("failed to write payload to temp file"), err)
return errorutil.NewWithErr(err).Msgf("failed to write payload to temp file")
}
defer func() {
_ = FileLoc.Close()
@@ -1046,7 +1046,7 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error {
}
if !sliceutil.ElementsMatch(gotReqToEndpoints, []string{"/one", "/two", "/one", "/two"}) {
return errkit.New(fmt.Sprintf("%s: expected requests to be sent to `/one` and `/two` endpoints but were sent to `%v`", filePath, gotReqToEndpoints)).Build()
return errorutil.NewWithTag(filePath, "expected requests to be sent to `/one` and `/two` endpoints but were sent to `%v`", gotReqToEndpoints)
}
return nil
}
+2 -2
View File
@@ -10,7 +10,7 @@ import (
"github.com/julienschmidt/httprouter"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
permissionutil "github.com/projectdiscovery/utils/permission"
)
@@ -223,7 +223,7 @@ type loadTemplateWithID struct{}
func (h *loadTemplateWithID) Execute(nooop string) error {
results, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", "scanme.sh", "-id", "self-signed-ssl")
if err != nil {
return errkit.Append(errkit.New("failed to load template with id"), err)
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
return expectResultsCount(results, 1)
}
+4 -4
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
var profileLoaderTestcases = []TestCaseInfo{
@@ -18,7 +18,7 @@ type profileLoaderByRelFile struct{}
func (h *profileLoaderByRelFile) Execute(testName string) error {
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", "cloud.yml")
if err != nil {
return errkit.Append(errkit.New("failed to load template with id"), err)
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
if len(results) <= 10 {
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results))
@@ -31,7 +31,7 @@ type profileLoaderById struct{}
func (h *profileLoaderById) Execute(testName string) error {
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", "cloud")
if err != nil {
return errkit.Append(errkit.New("failed to load template with id"), err)
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
if len(results) <= 10 {
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 10, len(results))
@@ -45,7 +45,7 @@ type customProfileLoader struct{}
func (h *customProfileLoader) Execute(filepath string) error {
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", filepath)
if err != nil {
return errkit.Append(errkit.New("failed to load template with id"), err)
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
}
if len(results) < 1 {
return fmt.Errorf("incorrect result: expected more results than %d, got %v", 1, len(results))
+2 -2
View File
@@ -4,7 +4,7 @@ import (
"os"
"github.com/projectdiscovery/nuclei/v3/pkg/testutils"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
var templatesDirTestCases = []TestCaseInfo{
@@ -17,7 +17,7 @@ type templateDirWithTargetTest struct{}
func (h *templateDirWithTargetTest) Execute(filePath string) error {
tempdir, err := os.MkdirTemp("", "nuclei-update-dir-*")
if err != nil {
return errkit.Append(errkit.New("failed to create temp dir"), err)
return errorutil.NewWithErr(err).Msgf("failed to create temp dir")
}
defer func() {
_ = os.RemoveAll(tempdir)
+9 -2
View File
@@ -39,7 +39,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/types/scanstrategy"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/monitor"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
unitutils "github.com/projectdiscovery/utils/unit"
updateutils "github.com/projectdiscovery/utils/update"
@@ -187,7 +187,7 @@ func main() {
options.Logger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
err := nucleiRunner.SaveResumeConfig(resumeFileName)
if err != nil {
return errkit.Append(errkit.New("couldn't create crash resume file"), err)
return errorutil.NewWithErr(err).Msgf("couldn't create crash resume file")
}
return nil
})
@@ -757,3 +757,10 @@ func findProfilePathById(profileId, templatesDir string) string {
}
return profilePath
}
func init() {
// print stacktrace of errors in debug mode
if strings.EqualFold(os.Getenv("DEBUG"), "true") {
errorutil.ShowStackTrace = true
}
}
+23 -23
View File
@@ -23,7 +23,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"gopkg.in/yaml.v3"
)
@@ -243,7 +243,7 @@ func enhanceTemplate(data string) (string, bool, error) {
return data, false, err
}
if resp.StatusCode != 200 {
return data, false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build()
return data, false, errorutil.New("unexpected status code: %v", resp.Status)
}
var templateResp TemplateResp
if err := json.NewDecoder(resp.Body).Decode(&templateResp); err != nil {
@@ -254,20 +254,20 @@ func enhanceTemplate(data string) (string, bool, error) {
}
if templateResp.ValidateErrorCount > 0 {
if len(templateResp.ValidateError) > 0 {
return data, false, errkit.New(fmt.Sprintf("validate: %s: at line %v", templateResp.ValidateError[0].Message, templateResp.ValidateError[0].Mark.Line)).Build()
return data, false, errorutil.NewWithTag("validate", templateResp.ValidateError[0].Message+": at line %v", templateResp.ValidateError[0].Mark.Line)
}
return data, false, errkit.New("validate: validation failed").Build()
return data, false, errorutil.New("validation failed").WithTag("validate")
}
if templateResp.Error.Name != "" {
return data, false, errkit.New(templateResp.Error.Name).Build()
return data, false, errorutil.New("%s", templateResp.Error.Name)
}
if strings.TrimSpace(templateResp.Enhanced) == "" && !templateResp.Lint {
if templateResp.LintError.Reason != "" {
return data, false, errkit.New(fmt.Sprintf("lint: %s : at line %v", templateResp.LintError.Reason, templateResp.LintError.Mark.Line)).Build()
return data, false, errorutil.NewWithTag("lint", templateResp.LintError.Reason+" : at line %v", templateResp.LintError.Mark.Line)
}
return data, false, errkit.New(fmt.Sprintf("lint: at line: %v", templateResp.LintError.Mark.Line)).Build()
return data, false, errorutil.NewWithTag("lint", "at line: %v", templateResp.LintError.Mark.Line)
}
return data, false, errkit.New("template enhance failed").Build()
return data, false, errorutil.New("template enhance failed")
}
// formatTemplate formats template data using templateman format api
@@ -277,7 +277,7 @@ func formatTemplate(data string) (string, bool, error) {
return data, false, err
}
if resp.StatusCode != 200 {
return data, false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build()
return data, false, errorutil.New("unexpected status code: %v", resp.Status)
}
var templateResp TemplateResp
if err := json.NewDecoder(resp.Body).Decode(&templateResp); err != nil {
@@ -288,20 +288,20 @@ func formatTemplate(data string) (string, bool, error) {
}
if templateResp.ValidateErrorCount > 0 {
if len(templateResp.ValidateError) > 0 {
return data, false, errkit.New(fmt.Sprintf("validate: %s: at line %v", templateResp.ValidateError[0].Message, templateResp.ValidateError[0].Mark.Line)).Build()
return data, false, errorutil.NewWithTag("validate", templateResp.ValidateError[0].Message+": at line %v", templateResp.ValidateError[0].Mark.Line)
}
return data, false, errkit.New("validate: validation failed").Build()
return data, false, errorutil.New("validation failed").WithTag("validate")
}
if templateResp.Error.Name != "" {
return data, false, errkit.New(templateResp.Error.Name).Build()
return data, false, errorutil.New("%s", templateResp.Error.Name)
}
if strings.TrimSpace(templateResp.Updated) == "" && !templateResp.Lint {
if templateResp.LintError.Reason != "" {
return data, false, errkit.New(fmt.Sprintf("lint: %s : at line %v", templateResp.LintError.Reason, templateResp.LintError.Mark.Line)).Build()
return data, false, errorutil.NewWithTag("lint", templateResp.LintError.Reason+" : at line %v", templateResp.LintError.Mark.Line)
}
return data, false, errkit.New(fmt.Sprintf("lint: at line: %v", templateResp.LintError.Mark.Line)).Build()
return data, false, errorutil.NewWithTag("lint", "at line: %v", templateResp.LintError.Mark.Line)
}
return data, false, errkit.New("template format failed").Build()
return data, false, errorutil.New("template format failed")
}
// lintTemplate lints template data using templateman lint api
@@ -311,7 +311,7 @@ func lintTemplate(data string) (bool, error) {
return false, err
}
if resp.StatusCode != 200 {
return false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build()
return false, errorutil.New("unexpected status code: %v", resp.Status)
}
var lintResp TemplateLintResp
if err := json.NewDecoder(resp.Body).Decode(&lintResp); err != nil {
@@ -321,9 +321,9 @@ func lintTemplate(data string) (bool, error) {
return true, nil
}
if lintResp.LintError.Reason != "" {
return false, errkit.New(fmt.Sprintf("lint: %s : at line %v", lintResp.LintError.Reason, lintResp.LintError.Mark.Line)).Build()
return false, errorutil.NewWithTag("lint", lintResp.LintError.Reason+" : at line %v", lintResp.LintError.Mark.Line)
}
return false, errkit.New(fmt.Sprintf("lint: at line: %v", lintResp.LintError.Mark.Line)).Build()
return false, errorutil.NewWithTag("lint", "at line: %v", lintResp.LintError.Mark.Line)
}
// validateTemplate validates template data using templateman validate api
@@ -333,7 +333,7 @@ func validateTemplate(data string) (bool, error) {
return false, err
}
if resp.StatusCode != 200 {
return false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build()
return false, errorutil.New("unexpected status code: %v", resp.Status)
}
var validateResp TemplateResp
if err := json.NewDecoder(resp.Body).Decode(&validateResp); err != nil {
@@ -344,14 +344,14 @@ func validateTemplate(data string) (bool, error) {
}
if validateResp.ValidateErrorCount > 0 {
if len(validateResp.ValidateError) > 0 {
return false, errkit.New(fmt.Sprintf("validate: %s: at line %v", validateResp.ValidateError[0].Message, validateResp.ValidateError[0].Mark.Line)).Build()
return false, errorutil.NewWithTag("validate", validateResp.ValidateError[0].Message+": at line %v", validateResp.ValidateError[0].Mark.Line)
}
return false, errkit.New("validate: validation failed").Build()
return false, errorutil.New("validation failed").WithTag("validate")
}
if validateResp.Error.Name != "" {
return false, errkit.New(validateResp.Error.Name).Build()
return false, errorutil.New("%s", validateResp.Error.Name)
}
return false, errkit.New("template validation failed").Build()
return false, errorutil.New("template validation failed")
}
// parseAndAddMaxRequests parses and adds max requests to templates
+11 -11
View File
@@ -20,12 +20,12 @@ require (
github.com/olekukonko/tablewriter v1.0.8
github.com/pkg/errors v0.9.1
github.com/projectdiscovery/clistats v0.1.1
github.com/projectdiscovery/fastdialer v0.4.4
github.com/projectdiscovery/hmap v0.0.92
github.com/projectdiscovery/fastdialer v0.4.1
github.com/projectdiscovery/hmap v0.0.91
github.com/projectdiscovery/interactsh v1.2.4
github.com/projectdiscovery/rawhttp v0.1.90
github.com/projectdiscovery/retryabledns v1.0.105
github.com/projectdiscovery/retryablehttp-go v1.0.119
github.com/projectdiscovery/retryabledns v1.0.103
github.com/projectdiscovery/retryablehttp-go v1.0.117
github.com/projectdiscovery/yamldoc-go v1.0.6
github.com/remeh/sizedwaitgroup v1.0.0
github.com/rs/xid v1.6.0
@@ -35,7 +35,7 @@ require (
github.com/spf13/cast v1.9.2
github.com/syndtr/goleveldb v1.0.0
github.com/valyala/fasttemplate v1.2.2
github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39
github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b
go.uber.org/multierr v1.11.0
golang.org/x/net v0.41.0
golang.org/x/oauth2 v0.30.0
@@ -98,14 +98,14 @@ require (
github.com/projectdiscovery/httpx v1.7.0
github.com/projectdiscovery/mapcidr v1.1.34
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
github.com/projectdiscovery/networkpolicy v0.1.18
github.com/projectdiscovery/networkpolicy v0.1.17
github.com/projectdiscovery/ratelimit v0.0.81
github.com/projectdiscovery/rdap v0.9.0
github.com/projectdiscovery/sarif v0.0.1
github.com/projectdiscovery/tlsx v1.1.9
github.com/projectdiscovery/uncover v1.1.0
github.com/projectdiscovery/useragent v0.0.101
github.com/projectdiscovery/utils v0.4.23
github.com/projectdiscovery/utils v0.4.21
github.com/projectdiscovery/wappalyzergo v0.2.36
github.com/redis/go-redis/v9 v9.11.0
github.com/seh-msft/burpxml v1.0.1
@@ -191,7 +191,7 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/docker/cli v27.4.1+incompatible // indirect
github.com/docker/docker v28.0.0+incompatible // indirect
github.com/docker/docker v27.1.1+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
@@ -199,7 +199,7 @@ require (
github.com/felixge/fgprof v0.9.5 // indirect
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gaissmai/bart v0.20.5 // indirect
github.com/gaissmai/bart v0.20.4 // indirect
github.com/geoffgarside/ber v1.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
@@ -213,7 +213,7 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
@@ -298,7 +298,7 @@ require (
github.com/projectdiscovery/freeport v0.0.7 // indirect
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb // indirect
github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 // indirect
github.com/refraction-networking/utls v1.7.1 // indirect
github.com/refraction-networking/utls v1.7.0 // indirect
github.com/sashabaranov/go-openai v1.37.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
+22 -22
View File
@@ -297,8 +297,8 @@ github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZ
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI=
github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.0.0+incompatible h1:Olh0KS820sJ7nPsBKChVhk5pzqcwDR15fumfAd/p9hM=
github.com/docker/docker v28.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -332,8 +332,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gaissmai/bart v0.20.5 h1:ehoWZWQ7j//qt0K0Zs4i9hpoPpbgqsMQiR8W2QPJh+c=
github.com/gaissmai/bart v0.20.5/go.mod h1:cEed+ge8dalcbpi8wtS9x9m2hn/fNJH5suhdGQOHnYk=
github.com/gaissmai/bart v0.20.4 h1:Ik47r1fy3jRVU+1eYzKSW3ho2UgBVTVnUS8O993584U=
github.com/gaissmai/bart v0.20.4/go.mod h1:cEed+ge8dalcbpi8wtS9x9m2hn/fNJH5suhdGQOHnYk=
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
@@ -397,8 +397,8 @@ github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI6
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goburrow/cache v0.1.4 h1:As4KzO3hgmzPlnaMniZU9+VmoNYseUhuELbxy9mRBfw=
github.com/goburrow/cache v0.1.4/go.mod h1:cDFesZDnIlrHoNlMYqqMpCRawuXulgx+y7mXU8HZ+/c=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
@@ -769,8 +769,8 @@ github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB7
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
github.com/projectdiscovery/dsl v0.5.0 h1:3HHY14FNmdwWXq3pi9dd8JjUHQzskZjLD/pZKVx5Vi4=
github.com/projectdiscovery/dsl v0.5.0/go.mod h1:Fr+zIQJfMNy+RTj5KFgozfvDaiQQEKMyrKXl75aGgxY=
github.com/projectdiscovery/fastdialer v0.4.4 h1:QeVbOnTMPhc/IOkkj2AP2q9hu5E1oCBPiLwEvPSR6A8=
github.com/projectdiscovery/fastdialer v0.4.4/go.mod h1:a0FNUOcmW6g6JhjaJ2+YkCpFFkQeCbetq/d9Zo4G3rQ=
github.com/projectdiscovery/fastdialer v0.4.1 h1:kp6Q0odo0VZ0vZIGOn+q9aLgBSk6uYoD1MsjCAH8+h4=
github.com/projectdiscovery/fastdialer v0.4.1/go.mod h1:875Wlggf0JAz+fDIPwUQeeBqEF6nJA71XVrjuTZCV7I=
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
github.com/projectdiscovery/fasttemplate v0.0.2/go.mod h1:XYWWVMxnItd+r0GbjA1GCsUopMw1/XusuQxdyAIHMCw=
github.com/projectdiscovery/freeport v0.0.7 h1:Q6uXo/j8SaV/GlAHkEYQi8WQoPXyJWxyspx+aFmz9Qk=
@@ -787,8 +787,8 @@ github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBD
github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
github.com/projectdiscovery/gozero v0.0.3 h1:tsYkrSvWw4WdIUJyisd4MB1vRiw1X57TuVVk3p8Z3G8=
github.com/projectdiscovery/gozero v0.0.3/go.mod h1:MpJ37Dsh94gy2EKqaemdeh+CzduGVB2SDfhr6Upsjew=
github.com/projectdiscovery/hmap v0.0.92 h1:NHGDFVJzc7b8bDuIjss7SxX5LJla9py/RxC4lri+uBo=
github.com/projectdiscovery/hmap v0.0.92/go.mod h1:IKezuOhPPwrmPusmhLuwuGsD8+fniyy6jx4gFTOZOnI=
github.com/projectdiscovery/hmap v0.0.91 h1:8vSTU+3hmMfA5Qd14ceq4j7wnUVUJcXdqQgqbsFBea0=
github.com/projectdiscovery/hmap v0.0.91/go.mod h1:BxEg8WXqxqaOADPZ+xp2X6BY+znfV8dusCSGSFnsU3c=
github.com/projectdiscovery/httpx v1.7.0 h1:s7ZgF2ZAt9pQYkBuY5F6SjyNYbYrl7eiIzOm/6hBZ/E=
github.com/projectdiscovery/httpx v1.7.0/go.mod h1:D0HLzSy+/G6w01FtRORGyfwVwWlUPAFIc8wyEj/lcVg=
github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI=
@@ -801,18 +801,18 @@ github.com/projectdiscovery/mapcidr v1.1.34 h1:udr83vQ7oz3kEOwlsU6NC6o08leJzSDQt
github.com/projectdiscovery/mapcidr v1.1.34/go.mod h1:1+1R6OkKSAKtWDXE9RvxXtXPoajXTYX0eiEdkqlhQqQ=
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw1pfT6bg35NiN7yd1XKtJap5Nk6lMwQ0RNi8=
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
github.com/projectdiscovery/networkpolicy v0.1.18 h1:DAeP73SvcuT4evaohNS7BPELw+VtvcVt4PaTK3fC1qA=
github.com/projectdiscovery/networkpolicy v0.1.18/go.mod h1:2yWanKsU2oBZ75ch94IsEQy6hByFp+3oTiSyC6ew3TE=
github.com/projectdiscovery/networkpolicy v0.1.17 h1:A/axsarHnVgv8bPB2vuI/7Hg0PrFBL+KGFSurJlDzx0=
github.com/projectdiscovery/networkpolicy v0.1.17/go.mod h1:Bwgfqbb2RAMIQ0OvfVofoFQFV3DitnXZZX5DkQMnjx8=
github.com/projectdiscovery/ratelimit v0.0.81 h1:u6lW+rAhS/UO0amHTYmYLipPK8NEotA9521hdojBtgI=
github.com/projectdiscovery/ratelimit v0.0.81/go.mod h1:tK04WXHuC4i6AsFkByInODSNf45gd9sfaMHzmy2bAsA=
github.com/projectdiscovery/rawhttp v0.1.90 h1:LOSZ6PUH08tnKmWsIwvwv1Z/4zkiYKYOSZ6n+8RFKtw=
github.com/projectdiscovery/rawhttp v0.1.90/go.mod h1:VZYAM25UI/wVB3URZ95ZaftgOnsbphxyAw/XnQRRz4Y=
github.com/projectdiscovery/rdap v0.9.0 h1:wPhHx5pQ2QI+WGhyNb2PjhTl0NtB39Nk7YFZ9cp8ZGA=
github.com/projectdiscovery/rdap v0.9.0/go.mod h1:zk4yrJFQ2Hy36Aqk+DvotYQxYAeALaCJ5ORySkff36Q=
github.com/projectdiscovery/retryabledns v1.0.105 h1:G8ln01igkNTQ5xvMY5K4cx5XIfKGTwGH6aZxWxBKMqc=
github.com/projectdiscovery/retryabledns v1.0.105/go.mod h1:3EZKhRL1rokqYR4q5qKK1eLBEe8mSzgtzkMOJilO1Ok=
github.com/projectdiscovery/retryablehttp-go v1.0.119 h1:Lpjb6gCWpIvCCX8GultM8zlaQEmFOci1dS33k9Ll4gw=
github.com/projectdiscovery/retryablehttp-go v1.0.119/go.mod h1:x29gqkLERRzw0znJDu5ORhphBaVin8FtK0+jCvCx4os=
github.com/projectdiscovery/retryabledns v1.0.103 h1:rPnoMTK+CXLbO8kT7ODtwbhyQGAUpJsqhVq8AAvu1bs=
github.com/projectdiscovery/retryabledns v1.0.103/go.mod h1:sfu91YrZkb8Ccvij8YDTV96cQt69IPqnfa+OEFUke1o=
github.com/projectdiscovery/retryablehttp-go v1.0.117 h1:xU9H2ONb9iG25Sm4eCinDhb4kt/s542BomUZAx4CGEs=
github.com/projectdiscovery/retryablehttp-go v1.0.117/go.mod h1:pAQWFh6lg9Gmno5zrQxbfuAbc9OvIugl5P9kaoXztgM=
github.com/projectdiscovery/sarif v0.0.1 h1:C2Tyj0SGOKbCLgHrx83vaE6YkzXEVrMXYRGLkKCr/us=
github.com/projectdiscovery/sarif v0.0.1/go.mod h1:cEYlDu8amcPf6b9dSakcz2nNnJsoz4aR6peERwV+wuQ=
github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
@@ -823,8 +823,8 @@ github.com/projectdiscovery/uncover v1.1.0 h1:UDp/qLZn78YZb6VPoOrfyP1vz+ojEx8VrT
github.com/projectdiscovery/uncover v1.1.0/go.mod h1:2rXINmMe/lmVAt2jn9CpAOs9An57/JEeLZobY3Z9kUs=
github.com/projectdiscovery/useragent v0.0.101 h1:8A+XOJ/nIH+WqW8ogLxJ/psemGp8ATQ2/GuKroJ/81E=
github.com/projectdiscovery/useragent v0.0.101/go.mod h1:RGoRw1BQ/lJnhYMbMpEKjyAAgCaDCr/+GsULo5yEJ2I=
github.com/projectdiscovery/utils v0.4.23 h1:fi6AVPIh2laomWO+Yy6G8YhvM4c2fDmQ/Viio6VZgyw=
github.com/projectdiscovery/utils v0.4.23/go.mod h1:2K2ymMPnp4/Zao5QulCDJzKjxdyZPsucQm6Fyo09JlA=
github.com/projectdiscovery/utils v0.4.21 h1:yAothTUSF6NwZ9yoC4iGe5gSBrovqKR9JwwW3msxk3Q=
github.com/projectdiscovery/utils v0.4.21/go.mod h1:HJuJFqjB6EmVaDl0ilFPKvLoMaX2GyE6Il2TqKXNs8I=
github.com/projectdiscovery/wappalyzergo v0.2.36 h1:g/E2gatdYcmLKk9R81vrkq4RdpACpYgN1fuyY3041eE=
github.com/projectdiscovery/wappalyzergo v0.2.36/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA=
github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas=
@@ -855,8 +855,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs=
github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/refraction-networking/utls v1.7.1 h1:dxg+jla3uocgN8HtX+ccwDr68uCBBO3qLrkZUbqkcw0=
github.com/refraction-networking/utls v1.7.1/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
github.com/refraction-networking/utls v1.7.0 h1:9JTnze/Md74uS3ZWiRAabityY0un69rOLXsBf8LGgTs=
github.com/refraction-networking/utls v1.7.0/go.mod h1:lV0Gwc1/Fi+HYH8hOtgFRdHfKo4FKSn6+FdyOz9hRms=
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -976,8 +976,8 @@ github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8L
github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
github.com/weppos/publicsuffix-go v0.30.0/go.mod h1:kBi8zwYnR0zrbm8RcuN1o9Fzgpnnn+btVN8uWPMyXAY=
github.com/weppos/publicsuffix-go v0.30.2/go.mod h1:/hGscit36Yt+wammfBBwdMdxBT8btsTt6KvwO9OvMyM=
github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39 h1:Bz/zVM/LoGZ9IztGBHrq2zlFQQbEG8dBYnxb4hamIHM=
github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39/go.mod h1:2oFzEwGYI7lhiqG0YkkcKa6VcpjVinQbWxaPzytDmLA=
github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b h1:PFOWooJRLwIuZk9i3ihzKzZffPrAVyOCzPInvLbn140=
github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b/go.mod h1:EACzvcFHnxqmDapI/oqMjtpXz+mtjNzJe7r1zhRczZ0=
github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
+9 -9
View File
@@ -19,7 +19,7 @@ import (
"github.com/projectdiscovery/retryablehttp-go"
pdcpauth "github.com/projectdiscovery/utils/auth/pdcp"
"github.com/projectdiscovery/utils/env"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
unitutils "github.com/projectdiscovery/utils/unit"
updateutils "github.com/projectdiscovery/utils/update"
urlutil "github.com/projectdiscovery/utils/url"
@@ -77,11 +77,11 @@ func NewUploadWriter(ctx context.Context, logger *gologger.Logger, creds *pdcpau
output.WithJson(true, true),
)
if err != nil {
return nil, errkit.Append(errkit.New("could not create output writer"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not create output writer")
}
tmp, err := urlutil.Parse(creds.Server)
if err != nil {
return nil, errkit.Append(errkit.New("could not parse server url"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not parse server url")
}
tmp.Path = uploadEndpoint
tmp.Update()
@@ -199,7 +199,7 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) {
// uploadChunk uploads a chunk of data to the server
func (u *UploadWriter) uploadChunk(buff *bytes.Buffer) error {
if err := u.upload(buff.Bytes()); err != nil {
return errkit.Append(errkit.New("could not upload chunk"), err)
return errorutil.NewWithErr(err).Msgf("could not upload chunk")
}
// if successful, reset the buffer
buff.Reset()
@@ -211,25 +211,25 @@ func (u *UploadWriter) uploadChunk(buff *bytes.Buffer) error {
func (u *UploadWriter) upload(data []byte) error {
req, err := u.getRequest(data)
if err != nil {
return errkit.Append(errkit.New("could not create upload request"), err)
return errorutil.NewWithErr(err).Msgf("could not create upload request")
}
resp, err := u.client.Do(req)
if err != nil {
return errkit.Append(errkit.New("could not upload results"), err)
return errorutil.NewWithErr(err).Msgf("could not upload results")
}
defer func() {
_ = resp.Body.Close()
}()
bin, err := io.ReadAll(resp.Body)
if err != nil {
return errkit.Append(errkit.New("could not get id from response"), err)
return errorutil.NewWithErr(err).Msgf("could not get id from response")
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("could not upload results got status code %v on %v", resp.StatusCode, resp.Request.URL.String())
}
var uploadResp uploadResponse
if err := json.Unmarshal(bin, &uploadResp); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not unmarshal response got %v", string(bin))), err)
return errorutil.NewWithErr(err).Msgf("could not unmarshal response got %v", string(bin))
}
if uploadResp.ID != "" && u.scanID == "" {
u.scanID = uploadResp.ID
@@ -254,7 +254,7 @@ func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) {
}
req, err := retryablehttp.NewRequest(method, url, bytes.NewReader(bin))
if err != nil {
return nil, errkit.Append(errkit.New("could not create cloud upload request"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not create cloud upload request")
}
// add pdtm meta params
req.Params.Merge(updateutils.GetpdtmParams(config.Version))
+3 -3
View File
@@ -17,7 +17,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/scan"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/env"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
type AuthLazyFetchOptions struct {
@@ -32,7 +32,7 @@ func GetAuthTmplStore(opts *types.Options, catalog catalog.Catalog, execOpts *pr
for _, file := range opts.SecretsFile {
data, err := authx.GetTemplatePathsFromSecretFile(file)
if err != nil {
return nil, errkit.Append(errkit.New("failed to get template paths from secrets file"), err)
return nil, errorutil.NewWithErr(err).Msgf("failed to get template paths from secrets file")
}
tmpls = append(tmpls, data...)
}
@@ -58,7 +58,7 @@ func GetAuthTmplStore(opts *types.Options, catalog catalog.Catalog, execOpts *pr
cfg.StoreId = loader.AuthStoreId
store, err := loader.New(cfg)
if err != nil {
return nil, errkit.Append(errkit.New("failed to initialize dynamic auth templates store"), err)
return nil, errorutil.NewWithErr(err).Msgf("failed to initialize dynamic auth templates store")
}
return store, nil
}
+2 -2
View File
@@ -8,7 +8,7 @@ import (
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
proxyutils "github.com/projectdiscovery/utils/proxy"
)
@@ -50,7 +50,7 @@ func loadProxyServers(options *types.Options) error {
}
proxyURL, err := url.Parse(aliveProxy)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to parse proxy got %v", err)), err)
return errorutil.WrapfWithNil(err, "failed to parse proxy got %v", err)
}
if options.ProxyInternal {
_ = os.Setenv(HTTP_PROXY_ENV, proxyURL.String())
-8
View File
@@ -125,14 +125,6 @@ func New(options *types.Options) (*Runner, error) {
}
}
// if template list or template display is enabled, enable all templates
if options.TemplateList || options.TemplateDisplay {
options.EnableCodeTemplates = true
options.EnableFileTemplates = true
options.EnableSelfContainedTemplates = true
options.EnableGlobalMatchersTemplates = true
}
// check for custom template updates and update if available
ctm, err := customtemplates.NewCustomTemplatesManager(options)
if err != nil {
+9 -9
View File
@@ -102,7 +102,7 @@ type InteractshOpts interactsh.Options
func WithInteractshOptions(opts InteractshOpts) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("WithInteractshOptions")
return ErrOptionsNotSupported.Msgf("WithInteractshOptions")
}
optsPtr := &opts
e.interactshOpts = (*interactsh.Options)(optsPtr)
@@ -229,7 +229,7 @@ type StatsOptions struct {
func EnableStatsWithOpts(opts StatsOptions) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("EnableStatsWithOpts")
return ErrOptionsNotSupported.Msgf("EnableStatsWithOpts")
}
if opts.Interval == 0 {
opts.Interval = 5 //sec
@@ -257,7 +257,7 @@ type VerbosityOptions struct {
func WithVerbosity(opts VerbosityOptions) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("WithVerbosity")
return ErrOptionsNotSupported.Msgf("WithVerbosity")
}
e.opts.Verbose = opts.Verbose
e.opts.Silent = opts.Silent
@@ -290,7 +290,7 @@ type NetworkConfig struct {
func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("WithNetworkConfig")
return ErrOptionsNotSupported.Msgf("WithNetworkConfig")
}
e.opts.NoHostErrors = opts.DisableMaxHostErr
e.opts.MaxHostError = opts.MaxHostError
@@ -321,7 +321,7 @@ func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions {
func WithProxy(proxy []string, proxyInternalRequests bool) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("WithProxy")
return ErrOptionsNotSupported.Msgf("WithProxy")
}
e.opts.Proxy = proxy
e.opts.ProxyInternal = proxyInternalRequests
@@ -346,7 +346,7 @@ type OutputWriter output.Writer
func UseOutputWriter(writer OutputWriter) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("UseOutputWriter")
return ErrOptionsNotSupported.Msgf("UseOutputWriter")
}
e.customWriter = writer
return nil
@@ -361,7 +361,7 @@ type StatsWriter progress.Progress
func UseStatsWriter(writer StatsWriter) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("UseStatsWriter")
return ErrOptionsNotSupported.Msgf("UseStatsWriter")
}
e.customProgress = writer
return nil
@@ -375,7 +375,7 @@ func UseStatsWriter(writer StatsWriter) NucleiSDKOptions {
func WithTemplateUpdateCallback(disableTemplatesAutoUpgrade bool, callback func(newVersion string)) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("WithTemplateUpdateCallback")
return ErrOptionsNotSupported.Msgf("WithTemplateUpdateCallback")
}
e.disableTemplatesAutoUpgrade = disableTemplatesAutoUpgrade
e.onUpdateAvailableCallback = callback
@@ -387,7 +387,7 @@ func WithTemplateUpdateCallback(disableTemplatesAutoUpgrade bool, callback func(
func WithSandboxOptions(allowLocalFileAccess bool, restrictLocalNetworkAccess bool) NucleiSDKOptions {
return func(e *NucleiEngine) error {
if e.mode == threadSafe {
return ErrOptionsNotSupported("WithSandboxOptions")
return ErrOptionsNotSupported.Msgf("WithSandboxOptions")
}
e.opts.AllowLocalFileAccess = allowLocalFileAccess
e.opts.RestrictLocalNetworkAccess = restrictLocalNetworkAccess
+3 -3
View File
@@ -13,7 +13,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/ratelimit"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"github.com/rs/xid"
)
@@ -147,13 +147,13 @@ func (e *ThreadSafeNucleiEngine) ExecuteNucleiWithOptsCtx(ctx context.Context, t
// load templates
workflowLoader, err := workflow.NewLoader(unsafeOpts.executerOpts)
if err != nil {
return errkit.Append(errkit.New("Could not create workflow loader"), err)
return errorutil.New("Could not create workflow loader: %s\n", err)
}
unsafeOpts.executerOpts.WorkflowLoader = workflowLoader
store, err := loader.New(loader.NewConfig(tmpEngine.opts, e.eng.catalog, unsafeOpts.executerOpts))
if err != nil {
return errkit.Append(errkit.New("Could not create loader client"), err)
return errorutil.New("Could not create loader client: %s\n", err)
}
store.Load()
+8 -12
View File
@@ -4,7 +4,6 @@ import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"sync"
@@ -29,7 +28,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/ratelimit"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"github.com/rs/xid"
)
@@ -38,18 +37,15 @@ type NucleiSDKOptions func(e *NucleiEngine) error
var (
// ErrNotImplemented is returned when a feature is not implemented
ErrNotImplemented = errkit.New("Not implemented").Build()
ErrNotImplemented = errorutil.New("Not implemented")
// ErrNoTemplatesAvailable is returned when no templates are available to execute
ErrNoTemplatesAvailable = errkit.New("No templates available").Build()
ErrNoTemplatesAvailable = errorutil.New("No templates available")
// ErrNoTargetsAvailable is returned when no targets are available to scan
ErrNoTargetsAvailable = errkit.New("No targets available").Build()
ErrNoTargetsAvailable = errorutil.New("No targets available")
// ErrOptionsNotSupported is returned when an option is not supported in thread safe mode
ErrOptionsNotSupported = errorutil.NewWithFmt("Option %v not supported in thread safe mode")
)
// ErrOptionsNotSupported returns an error when an option is not supported in thread safe mode
func ErrOptionsNotSupported(option string) error {
return errkit.New(fmt.Sprintf("Option %v not supported in thread safe mode", option)).Build()
}
type engineMode uint
const (
@@ -102,13 +98,13 @@ type NucleiEngine struct {
func (e *NucleiEngine) LoadAllTemplates() error {
workflowLoader, err := workflow.NewLoader(e.executerOpts)
if err != nil {
return errkit.Append(errkit.New("Could not create workflow loader"), err)
return errorutil.New("Could not create workflow loader: %s\n", err)
}
e.executerOpts.WorkflowLoader = workflowLoader
e.store, err = loader.New(loader.NewConfig(e.opts, e.catalog, e.executerOpts))
if err != nil {
return errkit.Append(errkit.New("Could not create loader client"), err)
return errorutil.New("Could not create loader client: %s\n", err)
}
e.store.Load()
e.templatesLoaded = true
+4 -4
View File
@@ -8,7 +8,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
sliceutil "github.com/projectdiscovery/utils/slice"
)
@@ -53,7 +53,7 @@ func (d *Dynamic) GetDomainAndDomainRegex() ([]string, []string) {
func (d *Dynamic) UnmarshalJSON(data []byte) error {
if d == nil {
return errkit.New("cannot unmarshal into nil Dynamic struct").Build()
return errorutil.New("cannot unmarshal into nil Dynamic struct")
}
// Use an alias type (auxiliary) to avoid a recursive call in this method.
@@ -72,10 +72,10 @@ func (d *Dynamic) UnmarshalJSON(data []byte) error {
func (d *Dynamic) Validate() error {
d.m = &sync.Mutex{}
if d.TemplatePath == "" {
return errkit.New(" template-path is required for dynamic secret").Build()
return errorutil.New(" template-path is required for dynamic secret")
}
if len(d.Variables) == 0 {
return errkit.New("variables are required for dynamic secret").Build()
return errorutil.New("variables are required for dynamic secret")
}
if d.Secret != nil {
+3 -3
View File
@@ -8,7 +8,7 @@ import (
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"github.com/projectdiscovery/utils/generic"
stringsutil "github.com/projectdiscovery/utils/strings"
"gopkg.in/yaml.v3"
@@ -237,7 +237,7 @@ func GetAuthDataFromYAML(data []byte) (*Authx, error) {
var auth Authx
err := yaml.Unmarshal(data, &auth)
if err != nil {
return nil, errkit.Append(errkit.New("could not unmarshal yaml"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not unmarshal yaml")
}
return &auth, nil
}
@@ -247,7 +247,7 @@ func GetAuthDataFromJSON(data []byte) (*Authx, error) {
var auth Authx
err := json.Unmarshal(data, &auth)
if err != nil {
return nil, errkit.Append(errkit.New("could not unmarshal json"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not unmarshal json")
}
return &auth, nil
}
+4 -5
View File
@@ -1,14 +1,13 @@
package authprovider
import (
"fmt"
"net"
"net/url"
"regexp"
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
urlutil "github.com/projectdiscovery/utils/url"
)
@@ -31,16 +30,16 @@ func NewFileAuthProvider(path string, callback authx.LazyFetchSecret) (AuthProvi
return nil, ErrNoSecrets
}
if len(store.Dynamic) > 0 && callback == nil {
return nil, errkit.New("lazy fetch callback is required for dynamic secrets").Build()
return nil, errorutil.New("lazy fetch callback is required for dynamic secrets")
}
for _, secret := range store.Secrets {
if err := secret.Validate(); err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("invalid secret in file: %s", path)), err)
return nil, errorutil.NewWithErr(err).Msgf("invalid secret in file: %s", path)
}
}
for i, dynamic := range store.Dynamic {
if err := dynamic.Validate(); err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("invalid dynamic in file: %s", path)), err)
return nil, errorutil.NewWithErr(err).Msgf("invalid dynamic in file: %s", path)
}
dynamic.SetLazyFetchCallback(callback)
store.Dynamic[i] = dynamic
+7 -10
View File
@@ -31,7 +31,7 @@ const (
CLIConfigFileName = "config.yaml"
ReportingConfigFilename = "reporting-config.yaml"
// Version is the current version of nuclei
Version = `v3.4.8`
Version = `v3.4.7`
// Directory Names of custom templates
CustomS3TemplatesDirName = "s3"
CustomGitHubTemplatesDirName = "github"
@@ -46,21 +46,18 @@ const (
// if the current version is outdated
func IsOutdatedVersion(current, latest string) bool {
if latest == "" {
// NOTE(dwisiswant0): if PDTM API call failed or returned empty, we
// cannot determine if templates are outdated w/o additional checks
// return false to avoid unnecessary updates.
return false
// if pdtm api call failed it's assumed that the current version is outdated
// and it will be confirmed while updating from GitHub
// this fixes `version string empty` errors
return true
}
current = trimDevIfExists(current)
currentVer, _ := semver.NewVersion(current)
newVer, _ := semver.NewVersion(latest)
if currentVer == nil || newVer == nil {
// fallback to naive comparison - return true only if they are different
return current != latest
// fallback to naive comparison
return current == latest
}
return newVer.GreaterThan(currentVer)
}
+10 -10
View File
@@ -13,7 +13,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/utils/env"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
folderutil "github.com/projectdiscovery/utils/folder"
)
@@ -140,13 +140,13 @@ func (c *Config) UpdateNucleiIgnoreHash() error {
if fileutil.FileExists(ignoreFilePath) {
bin, err := os.ReadFile(ignoreFilePath)
if err != nil {
return errkit.Append(errkit.New("could not read nuclei ignore file"), err)
return errorutil.NewWithErr(err).Msgf("could not read nuclei ignore file")
}
c.NucleiIgnoreHash = fmt.Sprintf("%x", md5.Sum(bin))
// write config to disk
return c.WriteTemplatesConfig()
}
return errkit.New("config: ignore file not found: could not update nuclei ignore hash").Build()
return errorutil.NewWithTag("config", "ignore file not found: could not update nuclei ignore hash")
}
// GetConfigDir returns the nuclei configuration directory
@@ -257,7 +257,7 @@ func (c *Config) SetTemplatesVersion(version string) error {
c.TemplateVersion = version
// write config to disk
if err := c.WriteTemplatesConfig(); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not write nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
return errorutil.NewWithErr(err).Msgf("could not write nuclei config file at %s", c.getTemplatesConfigFilePath())
}
return nil
}
@@ -265,15 +265,15 @@ func (c *Config) SetTemplatesVersion(version string) error {
// ReadTemplatesConfig reads the nuclei templates config file
func (c *Config) ReadTemplatesConfig() error {
if !fileutil.FileExists(c.getTemplatesConfigFilePath()) {
return errkit.New(fmt.Sprintf("config: nuclei config file at %s does not exist", c.getTemplatesConfigFilePath())).Build()
return errorutil.NewWithTag("config", "nuclei config file at %s does not exist", c.getTemplatesConfigFilePath())
}
var cfg *Config
bin, err := os.ReadFile(c.getTemplatesConfigFilePath())
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not read nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
return errorutil.NewWithErr(err).Msgf("could not read nuclei config file at %s", c.getTemplatesConfigFilePath())
}
if err := json.Unmarshal(bin, &cfg); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not unmarshal nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
return errorutil.NewWithErr(err).Msgf("could not unmarshal nuclei config file at %s", c.getTemplatesConfigFilePath())
}
// apply config
c.TemplatesDirectory = cfg.TemplatesDirectory
@@ -292,10 +292,10 @@ func (c *Config) WriteTemplatesConfig() error {
}
bin, err := json.Marshal(c)
if err != nil {
return errkit.Append(errkit.New("failed to marshal nuclei config"), err)
return errorutil.NewWithErr(err).Msgf("failed to marshal nuclei config")
}
if err = os.WriteFile(c.getTemplatesConfigFilePath(), bin, 0600); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to write nuclei config file at %s", c.getTemplatesConfigFilePath())), err)
return errorutil.NewWithErr(err).Msgf("failed to write nuclei config file at %s", c.getTemplatesConfigFilePath())
}
return nil
}
@@ -319,7 +319,7 @@ func (c *Config) getTemplatesConfigFilePath() string {
func (c *Config) createConfigDirIfNotExists() error {
if !fileutil.FolderExists(c.configDir) {
if err := fileutil.CreateFolder(c.configDir); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not create nuclei config directory at %s", c.configDir)), err)
return errorutil.NewWithErr(err).Msgf("could not create nuclei config directory at %s", c.configDir)
}
}
return nil
+15 -16
View File
@@ -3,7 +3,6 @@ package loader
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
@@ -15,7 +14,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/retryablehttp-go"
pdcpauth "github.com/projectdiscovery/utils/auth/pdcp"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
const (
@@ -34,27 +33,27 @@ type AITemplateResponse struct {
func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, error) {
prompt = strings.TrimSpace(prompt)
if len(prompt) < 5 {
return nil, errkit.New("Prompt is too short. Please provide a more descriptive prompt").Build()
return nil, errorutil.New("Prompt is too short. Please provide a more descriptive prompt")
}
if len(prompt) > 3000 {
return nil, errkit.New("Prompt is too long. Please limit to 3000 characters").Build()
return nil, errorutil.New("Prompt is too long. Please limit to 3000 characters")
}
template, templateID, err := generateAITemplate(prompt)
if err != nil {
return nil, errkit.New(fmt.Sprintf("Failed to generate template: %v", err)).Build()
return nil, errorutil.New("Failed to generate template: %v", err)
}
pdcpTemplateDir := filepath.Join(config.DefaultConfig.GetTemplateDir(), "pdcp")
if err := os.MkdirAll(pdcpTemplateDir, 0755); err != nil {
return nil, errkit.New(fmt.Sprintf("Failed to create pdcp template directory: %v", err)).Build()
return nil, errorutil.New("Failed to create pdcp template directory: %v", err)
}
templateFile := filepath.Join(pdcpTemplateDir, templateID+".yaml")
err = os.WriteFile(templateFile, []byte(template), 0644)
if err != nil {
return nil, errkit.New(fmt.Sprintf("Failed to generate template: %v", err)).Build()
return nil, errorutil.New("Failed to generate template: %v", err)
}
options.Logger.Info().Msgf("Generated template available at: https://cloud.projectdiscovery.io/templates/%s", templateID)
@@ -92,22 +91,22 @@ func generateAITemplate(prompt string) (string, string, error) {
}
jsonBody, err := json.Marshal(reqBody)
if err != nil {
return "", "", errkit.New(fmt.Sprintf("Failed to marshal request body: %v", err)).Build()
return "", "", errorutil.New("Failed to marshal request body: %v", err)
}
req, err := http.NewRequest(http.MethodPost, aiTemplateGeneratorAPIEndpoint, bytes.NewBuffer(jsonBody))
if err != nil {
return "", "", errkit.New(fmt.Sprintf("Failed to create HTTP request: %v", err)).Build()
return "", "", errorutil.New("Failed to create HTTP request: %v", err)
}
ph := pdcpauth.PDCPCredHandler{}
creds, err := ph.GetCreds()
if err != nil {
return "", "", errkit.New(fmt.Sprintf("Failed to get PDCP credentials: %v", err)).Build()
return "", "", errorutil.New("Failed to get PDCP credentials: %v", err)
}
if creds == nil {
return "", "", errkit.New("PDCP API Key not configured, Create one for free at https://cloud.projectdiscovery.io/").Build()
return "", "", errorutil.New("PDCP API Key not configured, Create one for free at https://cloud.projectdiscovery.io/")
}
req.Header.Set("Content-Type", "application/json")
@@ -115,28 +114,28 @@ func generateAITemplate(prompt string) (string, string, error) {
resp, err := retryablehttp.DefaultClient().Do(req)
if err != nil {
return "", "", errkit.New(fmt.Sprintf("Failed to send HTTP request: %v", err)).Build()
return "", "", errorutil.New("Failed to send HTTP request: %v", err)
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode == http.StatusUnauthorized {
return "", "", errkit.New("Invalid API Key or API Key not configured, Create one for free at https://cloud.projectdiscovery.io/").Build()
return "", "", errorutil.New("Invalid API Key or API Key not configured, Create one for free at https://cloud.projectdiscovery.io/")
}
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return "", "", errkit.New(fmt.Sprintf("API returned status code %d: %s", resp.StatusCode, string(body))).Build()
return "", "", errorutil.New("API returned status code %d: %s", resp.StatusCode, string(body))
}
var result AITemplateResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return "", "", errkit.New(fmt.Sprintf("Failed to decode API response: %v", err)).Build()
return "", "", errorutil.New("Failed to decode API response: %v", err)
}
if result.TemplateID == "" || result.Completion == "" {
return "", "", errkit.New("Failed to generate template").Build()
return "", "", errorutil.New("Failed to generate template")
}
return result.Completion, result.TemplateID, nil
+2 -2
View File
@@ -24,7 +24,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/utils/stats"
"github.com/projectdiscovery/nuclei/v3/pkg/workflows"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
sliceutil "github.com/projectdiscovery/utils/slice"
stringsutil "github.com/projectdiscovery/utils/strings"
syncutil "github.com/projectdiscovery/utils/sync"
@@ -238,7 +238,7 @@ func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error)
uri = handleTemplatesEditorURLs(uri)
remoteTemplates, _, err := getRemoteTemplatesAndWorkflows([]string{uri}, nil, store.config.RemoteTemplateDomainList)
if err != nil || len(remoteTemplates) == 0 {
return nil, errkit.Append(errkit.New(fmt.Sprintf("Could not load template %s: got %v", uri, remoteTemplates)), err)
return nil, errorutil.NewWithErr(err).Msgf("Could not load template %s: got %v", uri, remoteTemplates)
}
resp, err := retryablehttp.Get(remoteTemplates[0])
if err != nil {
+2 -3
View File
@@ -3,7 +3,6 @@ package customtemplates
import (
"bytes"
"context"
"fmt"
"os"
"path/filepath"
"strings"
@@ -13,7 +12,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
var _ Provider = &customTemplateAzureBlob{}
@@ -30,7 +29,7 @@ func NewAzureProviders(options *types.Options) ([]*customTemplateAzureBlob, erro
// Establish a connection to Azure and build a client object with which to download templates from Azure Blob Storage
azClient, err := getAzureBlobClient(options.AzureTenantID, options.AzureClientID, options.AzureClientSecret, options.AzureServiceURL)
if err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("Error establishing Azure Blob client for %s", options.AzureContainerName)), err)
return nil, errorutil.NewWithErr(err).Msgf("Error establishing Azure Blob client for %s", options.AzureContainerName)
}
// Create a new Azure Blob Storage container object
+2 -3
View File
@@ -3,14 +3,13 @@ package customtemplates
import (
"context"
"encoding/base64"
"fmt"
"os"
"path/filepath"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
gitlab "gitlab.com/gitlab-org/api/client-go"
)
@@ -29,7 +28,7 @@ func NewGitLabProviders(options *types.Options) ([]*customTemplateGitLabRepo, er
// Establish a connection to GitLab and build a client object with which to download templates from GitLab
gitLabClient, err := getGitLabClient(options.GitLabServerURL, options.GitLabToken)
if err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("Error establishing GitLab client for %s %s", options.GitLabServerURL, err)), err)
return nil, errorutil.NewWithErr(err).Msgf("Error establishing GitLab client for %s %s", options.GitLabServerURL, err)
}
// Create a new GitLab service client
+2 -3
View File
@@ -2,7 +2,6 @@ package customtemplates
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
@@ -15,7 +14,7 @@ import (
"github.com/projectdiscovery/gologger"
nucleiConfig "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
)
@@ -65,7 +64,7 @@ func NewS3Providers(options *types.Options) ([]*customTemplateS3Bucket, error) {
if options.AwsBucketName != "" && !options.AwsTemplateDisableDownload {
s3c, err := getS3Client(context.TODO(), options.AwsAccessKey, options.AwsSecretKey, options.AwsRegion, options.AwsProfile)
if err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("error downloading s3 bucket %s", options.AwsBucketName)), err)
return nil, errorutil.NewWithErr(err).Msgf("error downloading s3 bucket %s", options.AwsBucketName)
}
ctBucket := &customTemplateS3Bucket{
bucketName: options.AwsBucketName,
+5 -5
View File
@@ -4,7 +4,7 @@ import (
"context"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
type Provider interface {
@@ -38,7 +38,7 @@ func NewCustomTemplatesManager(options *types.Options) (*CustomTemplatesManager,
// Add GitHub providers
githubProviders, err := NewGitHubProviders(options)
if err != nil {
return nil, errkit.Append(errkit.New("could not create github providers for custom templates"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not create github providers for custom templates")
}
for _, v := range githubProviders {
ctm.providers = append(ctm.providers, v)
@@ -47,7 +47,7 @@ func NewCustomTemplatesManager(options *types.Options) (*CustomTemplatesManager,
// Add AWS S3 providers
s3Providers, err := NewS3Providers(options)
if err != nil {
return nil, errkit.Append(errkit.New("could not create s3 providers for custom templates"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not create s3 providers for custom templates")
}
for _, v := range s3Providers {
ctm.providers = append(ctm.providers, v)
@@ -56,7 +56,7 @@ func NewCustomTemplatesManager(options *types.Options) (*CustomTemplatesManager,
// Add Azure providers
azureProviders, err := NewAzureProviders(options)
if err != nil {
return nil, errkit.Append(errkit.New("could not create azure providers for custom templates"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not create azure providers for custom templates")
}
for _, v := range azureProviders {
ctm.providers = append(ctm.providers, v)
@@ -65,7 +65,7 @@ func NewCustomTemplatesManager(options *types.Options) (*CustomTemplatesManager,
// Add GitLab providers
gitlabProviders, err := NewGitLabProviders(options)
if err != nil {
return nil, errkit.Append(errkit.New("could not create gitlab providers for custom templates"), err)
return nil, errorutil.NewWithErr(err).Msgf("could not create gitlab providers for custom templates")
}
for _, v := range gitlabProviders {
ctm.providers = append(ctm.providers, v)
+11 -72
View File
@@ -14,19 +14,17 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/marker"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
mapsutil "github.com/projectdiscovery/utils/maps"
sliceutil "github.com/projectdiscovery/utils/slice"
urlutil "github.com/projectdiscovery/utils/url"
)
// ErrRuleNotApplicable returns a rule not applicable error
func ErrRuleNotApplicable(reason interface{}) error {
return errkit.New(fmt.Sprintf("rule not applicable: %v", reason)).Build()
}
var (
ErrRuleNotApplicable = errorutil.NewWithFmt("rule not applicable : %v")
)
// IsErrRuleNotApplicable checks if an error is due to rule not applicable
func IsErrRuleNotApplicable(err error) bool {
@@ -90,10 +88,10 @@ type GeneratedRequest struct {
// goroutines.
func (rule *Rule) Execute(input *ExecuteRuleInput) (err error) {
if !rule.isInputURLValid(input.Input) {
return ErrRuleNotApplicable(fmt.Sprintf("invalid input url: %v", input.Input.MetaInput.Input))
return ErrRuleNotApplicable.Msgf("invalid input url: %v", input.Input.MetaInput.Input)
}
if input.BaseRequest == nil && input.Input.MetaInput.ReqResp == nil {
return ErrRuleNotApplicable(fmt.Sprintf("both base request and reqresp are nil for %v", input.Input.MetaInput.Input))
return ErrRuleNotApplicable.Msgf("both base request and reqresp are nil for %v", input.Input.MetaInput.Input)
}
var finalComponentList []component.Component
@@ -145,7 +143,7 @@ func (rule *Rule) Execute(input *ExecuteRuleInput) (err error) {
}
if len(finalComponentList) == 0 {
return ErrRuleNotApplicable("no component matched on this rule")
return ErrRuleNotApplicable.Msgf("no component matched on this rule")
}
baseValues := input.Values
@@ -191,33 +189,6 @@ mainLoop:
return nil
}
// evaluateVars evaluates variables in a string using available executor options
func (rule *Rule) evaluateVars(input string) (string, error) {
if rule.options == nil {
return input, nil
}
data := generators.MergeMaps(
rule.options.Variables.GetAll(),
rule.options.Constants,
rule.options.Options.Vars.AsMap(),
)
exprs := expressions.FindExpressions(input, marker.ParenthesisOpen, marker.ParenthesisClose, data)
err := expressions.ContainsUnresolvedVariables(exprs...)
if err != nil {
return input, err
}
eval, err := expressions.Evaluate(input, data)
if err != nil {
return input, err
}
return eval, nil
}
// evaluateVarsWithInteractsh evaluates the variables with Interactsh URLs and updates them accordingly.
func (rule *Rule) evaluateVarsWithInteractsh(data map[string]interface{}, interactshUrls []string) (map[string]interface{}, []string) {
// Check if Interactsh options are configured
@@ -370,47 +341,23 @@ func (rule *Rule) Compile(generator *generators.PayloadGenerator, options *proto
if len(rule.Keys) > 0 {
rule.keysMap = make(map[string]struct{})
}
// eval vars in "keys"
for _, key := range rule.Keys {
evaluatedKey, err := rule.evaluateVars(key)
if err != nil {
return errors.Wrap(err, "could not evaluate key")
}
rule.keysMap[strings.ToLower(evaluatedKey)] = struct{}{}
rule.keysMap[strings.ToLower(key)] = struct{}{}
}
// eval vars in "values"
for _, value := range rule.ValuesRegex {
evaluatedValue, err := rule.evaluateVars(value)
if err != nil {
return errors.Wrap(err, "could not evaluate value regex")
}
compiled, err := regexp.Compile(evaluatedValue)
compiled, err := regexp.Compile(value)
if err != nil {
return errors.Wrap(err, "could not compile value regex")
}
rule.valuesRegex = append(rule.valuesRegex, compiled)
}
// eval vars in "keys-regex"
for _, value := range rule.KeysRegex {
evaluatedValue, err := rule.evaluateVars(value)
if err != nil {
return errors.Wrap(err, "could not evaluate key regex")
}
compiled, err := regexp.Compile(evaluatedValue)
compiled, err := regexp.Compile(value)
if err != nil {
return errors.Wrap(err, "could not compile key regex")
}
rule.keysRegex = append(rule.keysRegex, compiled)
}
if rule.ruleType != replaceRegexRuleType {
if rule.ReplaceRegex != "" {
return errors.Errorf("replace-regex is only applicable for replace and replace-regex rule types")
@@ -419,19 +366,11 @@ func (rule *Rule) Compile(generator *generators.PayloadGenerator, options *proto
if rule.ReplaceRegex == "" {
return errors.Errorf("replace-regex is required for replace-regex rule type")
}
evalReplaceRegex, err := rule.evaluateVars(rule.ReplaceRegex)
if err != nil {
return errors.Wrap(err, "could not evaluate replace regex")
}
compiled, err := regexp.Compile(evalReplaceRegex)
compiled, err := regexp.Compile(rule.ReplaceRegex)
if err != nil {
return errors.Wrap(err, "could not compile replace regex")
}
rule.replaceRegex = compiled
}
return nil
}
-221
View File
@@ -3,11 +3,6 @@ package fuzz
import (
"testing"
"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/variables"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/utils"
"github.com/stretchr/testify/require"
)
@@ -42,219 +37,3 @@ func TestRuleMatchKeyOrValue(t *testing.T) {
require.False(t, result, "could not get correct result")
})
}
func TestEvaluateVariables(t *testing.T) {
t.Run("keys", func(t *testing.T) {
rule := &Rule{
Keys: []string{"{{foo_var}}"},
Part: "query",
}
// mock
templateVars := variables.Variable{
InsertionOrderedStringMap: *utils.NewEmptyInsertionOrderedStringMap(1),
}
templateVars.Set("foo_var", "foo_var_value")
constants := map[string]interface{}{
"const_key": "const_value",
}
options := &types.Options{}
// runtime vars (to simulate CLI)
runtimeVars := goflags.RuntimeMap{}
_ = runtimeVars.Set("runtime_key=runtime_value")
options.Vars = runtimeVars
executorOpts := &protocols.ExecutorOptions{
Variables: templateVars,
Constants: constants,
Options: options,
}
err := rule.Compile(nil, executorOpts)
require.NoError(t, err, "could not compile rule")
result := rule.matchKeyOrValue("foo_var_value", "test_value")
require.True(t, result, "should match evaluated variable key")
result = rule.matchKeyOrValue("{{foo_var}}", "test_value")
require.False(t, result, "should not match unevaluated variable key")
})
t.Run("keys-regex", func(t *testing.T) {
rule := &Rule{
KeysRegex: []string{"^{{foo_var}}"},
Part: "query",
}
templateVars := variables.Variable{
InsertionOrderedStringMap: *utils.NewEmptyInsertionOrderedStringMap(1),
}
templateVars.Set("foo_var", "foo_var_value")
executorOpts := &protocols.ExecutorOptions{
Variables: templateVars,
Constants: map[string]interface{}{},
Options: &types.Options{},
}
err := rule.Compile(nil, executorOpts)
require.NoError(t, err, "could not compile rule")
result := rule.matchKeyOrValue("foo_var_value", "test_value")
require.True(t, result, "should match evaluated variable in regex")
result = rule.matchKeyOrValue("other_key", "test_value")
require.False(t, result, "should not match non-matching key")
})
t.Run("values-regex", func(t *testing.T) {
rule := &Rule{
ValuesRegex: []string{"{{foo_var}}"},
Part: "query",
}
templateVars := variables.Variable{
InsertionOrderedStringMap: *utils.NewEmptyInsertionOrderedStringMap(1),
}
templateVars.Set("foo_var", "test_pattern")
executorOpts := &protocols.ExecutorOptions{
Variables: templateVars,
Constants: map[string]interface{}{},
Options: &types.Options{},
}
err := rule.Compile(nil, executorOpts)
require.NoError(t, err, "could not compile rule")
result := rule.matchKeyOrValue("test_key", "test_pattern")
require.True(t, result, "should match evaluated variable in values regex")
result = rule.matchKeyOrValue("test_key", "other_value")
require.False(t, result, "should not match non-matching value")
})
// complex vars w/ consts and runtime vars
t.Run("complex-variables", func(t *testing.T) {
rule := &Rule{
Keys: []string{"{{template_var}}", "{{const_key}}", "{{runtime_key}}"},
Part: "query",
}
templateVars := variables.Variable{
InsertionOrderedStringMap: *utils.NewEmptyInsertionOrderedStringMap(1),
}
templateVars.Set("template_var", "template_value")
constants := map[string]interface{}{
"const_key": "const_value",
}
options := &types.Options{}
runtimeVars := goflags.RuntimeMap{}
_ = runtimeVars.Set("runtime_key=runtime_value")
options.Vars = runtimeVars
executorOpts := &protocols.ExecutorOptions{
Variables: templateVars,
Constants: constants,
Options: options,
}
err := rule.Compile(nil, executorOpts)
require.NoError(t, err, "could not compile rule")
result := rule.matchKeyOrValue("template_value", "test")
require.True(t, result, "should match template variable")
result = rule.matchKeyOrValue("const_value", "test")
require.True(t, result, "should match constant")
result = rule.matchKeyOrValue("runtime_value", "test")
require.True(t, result, "should match runtime variable")
result = rule.matchKeyOrValue("{{template_var}}", "test")
require.False(t, result, "should not match unevaluated template variable")
})
t.Run("invalid-variables", func(t *testing.T) {
rule := &Rule{
Keys: []string{"{{nonexistent_var}}"},
Part: "query",
}
executorOpts := &protocols.ExecutorOptions{
Variables: variables.Variable{
InsertionOrderedStringMap: *utils.NewEmptyInsertionOrderedStringMap(0),
},
Constants: map[string]interface{}{},
Options: &types.Options{},
}
err := rule.Compile(nil, executorOpts)
if err != nil {
require.Contains(t, err.Error(), "unresolved", "error should mention unresolved variables")
} else {
result := rule.matchKeyOrValue("some_key", "some_value")
require.False(t, result, "should not match when variables are unresolved")
}
})
t.Run("evaluateVars-function", func(t *testing.T) {
rule := &Rule{}
templateVars := variables.Variable{
InsertionOrderedStringMap: *utils.NewEmptyInsertionOrderedStringMap(1),
}
templateVars.Set("test_var", "test_value")
constants := map[string]interface{}{
"const_var": "const_value",
}
options := &types.Options{}
runtimeVars := goflags.RuntimeMap{}
_ = runtimeVars.Set("runtime_var=runtime_value")
options.Vars = runtimeVars
executorOpts := &protocols.ExecutorOptions{
Variables: templateVars,
Constants: constants,
Options: options,
}
rule.options = executorOpts
// Test simple var substitution
result, err := rule.evaluateVars("{{test_var}}")
require.NoError(t, err, "should evaluate template variable")
require.Equal(t, "test_value", result, "should return evaluated value")
// Test constant substitution
result, err = rule.evaluateVars("{{const_var}}")
require.NoError(t, err, "should evaluate constant")
require.Equal(t, "const_value", result, "should return constant value")
// Test runtime var substitution
result, err = rule.evaluateVars("{{runtime_var}}")
require.NoError(t, err, "should evaluate runtime variable")
require.Equal(t, "runtime_value", result, "should return runtime value")
// Test mixed content
result, err = rule.evaluateVars("prefix-{{test_var}}-suffix")
require.NoError(t, err, "should evaluate mixed content")
require.Equal(t, "prefix-test_value-suffix", result, "should return mixed evaluated content")
// Test unresolved var - should either fail during evaluation or return original string
result2, err := rule.evaluateVars("{{nonexistent}}")
if err != nil {
require.Contains(t, err.Error(), "unresolved", "should fail for unresolved variable")
} else {
// If no error, it should return the original unresolved variable
require.Equal(t, "{{nonexistent}}", result2, "should return original string for unresolved variable")
}
})
}
+9 -9
View File
@@ -20,7 +20,7 @@ import (
httpTypes "github.com/projectdiscovery/nuclei/v3/pkg/input/types"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"github.com/projectdiscovery/utils/generic"
mapsutil "github.com/projectdiscovery/utils/maps"
"github.com/valyala/fasttemplate"
@@ -395,7 +395,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error {
func GetGlobalParamsForSecurityRequirement(schema *openapi3.T, requirement *openapi3.SecurityRequirements) ([]*openapi3.ParameterRef, error) {
globalParams := openapi3.NewParameters()
if len(schema.Components.SecuritySchemes) == 0 {
return nil, errkit.New(fmt.Sprintf("openapi: security requirements (%+v) without any security schemes found in openapi file", schema.Security)).Build()
return nil, errorutil.NewWithTag("openapi", "security requirements (%+v) without any security schemes found in openapi file", schema.Security)
}
found := false
// this api is protected for each security scheme pull its corresponding scheme
@@ -415,11 +415,11 @@ schemaLabel:
}
if !found && len(security) > 1 {
// if this is case then both security schemes are required
return nil, errkit.New(fmt.Sprintf("openapi: security requirement (%+v) not found in openapi file", security)).Build()
return nil, errorutil.NewWithTag("openapi", "security requirement (%+v) not found in openapi file", security)
}
}
if !found {
return nil, errkit.New(fmt.Sprintf("openapi: security requirement (%+v) not found in openapi file", requirement)).Build()
return nil, errorutil.NewWithTag("openapi", "security requirement (%+v) not found in openapi file", requirement)
}
return globalParams, nil
@@ -428,12 +428,12 @@ schemaLabel:
// GenerateParameterFromSecurityScheme generates an example from a schema object
func GenerateParameterFromSecurityScheme(scheme *openapi3.SecuritySchemeRef) (*openapi3.Parameter, error) {
if !generic.EqualsAny(scheme.Value.Type, "http", "apiKey") {
return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme type (%s) found in openapi file", scheme.Value.Type)).Build()
return nil, errorutil.NewWithTag("openapi", "unsupported security scheme type (%s) found in openapi file", scheme.Value.Type)
}
if scheme.Value.Type == "http" {
// check scheme
if !generic.EqualsAny(scheme.Value.Scheme, "basic", "bearer") {
return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme (%s) found in openapi file", scheme.Value.Scheme)).Build()
return nil, errorutil.NewWithTag("openapi", "unsupported security scheme (%s) found in openapi file", scheme.Value.Scheme)
}
// HTTP authentication schemes basic or bearer use the Authorization header
headerName := scheme.Value.Name
@@ -458,10 +458,10 @@ func GenerateParameterFromSecurityScheme(scheme *openapi3.SecuritySchemeRef) (*o
if scheme.Value.Type == "apiKey" {
// validate name and in
if scheme.Value.Name == "" {
return nil, errkit.New(fmt.Sprintf("openapi: security scheme (%s) name is empty", scheme.Value.Type)).Build()
return nil, errorutil.NewWithTag("openapi", "security scheme (%s) name is empty", scheme.Value.Type)
}
if !generic.EqualsAny(scheme.Value.In, "query", "header", "cookie") {
return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme (%s) in (%s) found in openapi file", scheme.Value.Type, scheme.Value.In)).Build()
return nil, errorutil.NewWithTag("openapi", "unsupported security scheme (%s) in (%s) found in openapi file", scheme.Value.Type, scheme.Value.In)
}
// create parameters using the scheme
switch scheme.Value.In {
@@ -482,5 +482,5 @@ func GenerateParameterFromSecurityScheme(scheme *openapi3.SecuritySchemeRef) (*o
return c, nil
}
}
return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme type (%s) found in openapi file", scheme.Value.Type)).Build()
return nil, errorutil.NewWithTag("openapi", "unsupported security scheme type (%s) found in openapi file", scheme.Value.Type)
}
+3 -7
View File
@@ -13,19 +13,15 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
configTypes "github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
)
var (
ErrInactiveInput = fmt.Errorf("input is inactive")
ErrNotImplemented = errorutil.NewWithFmt("provider %s does not implement %s")
ErrInactiveInput = fmt.Errorf("input is inactive")
)
// ErrNotImplemented returns an error when a provider does not implement a method
func ErrNotImplemented(provider, method string) error {
return errkit.New(fmt.Sprintf("provider %s does not implement %s", provider, method)).Build()
}
const (
MultiFormatInputProvider = "MultiFormatInputProvider"
ListInputProvider = "ListInputProvider"
+18 -45
View File
@@ -17,7 +17,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/external/customtemplates"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
stringsutil "github.com/projectdiscovery/utils/strings"
updateutils "github.com/projectdiscovery/utils/update"
@@ -80,7 +80,7 @@ func (t *TemplateManager) FreshInstallIfNotExists() error {
}
gologger.Info().Msgf("nuclei-templates are not installed, installing...")
if err := t.installTemplatesAt(config.DefaultConfig.TemplatesDirectory); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to install templates at %s", config.DefaultConfig.TemplatesDirectory)), err)
return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", config.DefaultConfig.TemplatesDirectory)
}
if t.CustomTemplates != nil {
t.CustomTemplates.Download(context.TODO())
@@ -94,24 +94,7 @@ func (t *TemplateManager) UpdateIfOutdated() error {
if !fileutil.FolderExists(config.DefaultConfig.TemplatesDirectory) {
return t.FreshInstallIfNotExists()
}
needsUpdate := config.DefaultConfig.NeedsTemplateUpdate()
// NOTE(dwisiswant0): if PDTM API data is not available
// (LatestNucleiTemplatesVersion is empty) but we have a current template
// version, so we MUST verify against GitHub directly.
if !needsUpdate && config.DefaultConfig.LatestNucleiTemplatesVersion == "" && config.DefaultConfig.TemplateVersion != "" {
ghrd, err := updateutils.NewghReleaseDownloader(config.OfficialNucleiTemplatesRepoName)
if err == nil {
latestVersion := ghrd.Latest.GetTagName()
if config.IsOutdatedVersion(config.DefaultConfig.TemplateVersion, latestVersion) {
needsUpdate = true
gologger.Debug().Msgf("PDTM API unavailable, verified update needed via GitHub API: %s -> %s", config.DefaultConfig.TemplateVersion, latestVersion)
}
}
}
if needsUpdate {
if config.DefaultConfig.NeedsTemplateUpdate() {
return t.updateTemplatesAt(config.DefaultConfig.TemplatesDirectory)
}
return nil
@@ -121,7 +104,7 @@ func (t *TemplateManager) UpdateIfOutdated() error {
func (t *TemplateManager) installTemplatesAt(dir string) error {
if !fileutil.FolderExists(dir) {
if err := fileutil.CreateFolder(dir); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to create directory at %s", dir)), err)
return errorutil.NewWithErr(err).Msgf("failed to create directory at %s", dir)
}
}
if t.DisablePublicTemplates {
@@ -130,12 +113,12 @@ func (t *TemplateManager) installTemplatesAt(dir string) error {
}
ghrd, err := updateutils.NewghReleaseDownloader(config.OfficialNucleiTemplatesRepoName)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to install templates at %s", dir)), err)
return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir)
}
// write templates to disk
if err := t.writeTemplatesToDisk(ghrd, dir); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to write templates to disk at %s", dir)), err)
return errorutil.NewWithErr(err).Msgf("failed to write templates to disk at %s", dir)
}
gologger.Info().Msgf("Successfully installed nuclei-templates at %s", dir)
return nil
@@ -156,17 +139,10 @@ func (t *TemplateManager) updateTemplatesAt(dir string) error {
ghrd, err := updateutils.NewghReleaseDownloader(config.OfficialNucleiTemplatesRepoName)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to install templates at %s", dir)), err)
return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir)
}
latestVersion := ghrd.Latest.GetTagName()
currentVersion := config.DefaultConfig.TemplateVersion
if config.IsOutdatedVersion(currentVersion, latestVersion) {
gologger.Info().Msgf("Your current nuclei-templates %s are outdated. Latest is %s\n", currentVersion, latestVersion)
} else {
gologger.Debug().Msgf("Updating nuclei-templates from %s to %s (forced update)\n", currentVersion, latestVersion)
}
gologger.Info().Msgf("Your current nuclei-templates %s are outdated. Latest is %s\n", config.DefaultConfig.TemplateVersion, ghrd.Latest.GetTagName())
// write templates to disk
if err := t.writeTemplatesToDisk(ghrd, dir); err != nil {
@@ -177,7 +153,7 @@ func (t *TemplateManager) updateTemplatesAt(dir string) error {
newchecksums, err := t.getChecksumFromDir(dir)
if err != nil {
// unlikely this case will happen
return errkit.Append(errkit.New(fmt.Sprintf("failed to get checksums from %s after update", dir)), err)
return errorutil.NewWithErr(err).Msgf("failed to get checksums from %s after update", dir)
}
// summarize all changes
@@ -299,7 +275,7 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo
bin, err := io.ReadAll(r)
if err != nil {
// if error occurs, iteration also stops
return errkit.Append(errkit.New(fmt.Sprintf("failed to read file %s", uri)), err)
return errorutil.NewWithErr(err).Msgf("failed to read file %s", uri)
}
// TODO: It might be better to just download index file from nuclei templates repo
// instead of creating it from scratch
@@ -310,7 +286,7 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo
if oldPath != writePath {
// write new template at a new path and delete old template
if err := os.WriteFile(writePath, bin, f.Mode()); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to write file %s", uri)), err)
return errorutil.NewWithErr(err).Msgf("failed to write file %s", uri)
}
// after successful write, remove old template
if err := os.Remove(oldPath); err != nil {
@@ -325,20 +301,20 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo
}
err = ghrd.DownloadSourceWithCallback(!HideProgressBar, callbackFunc)
if err != nil {
return errkit.Append(errkit.New("failed to download templates"), err)
return errorutil.NewWithErr(err).Msgf("failed to download templates")
}
if err := config.DefaultConfig.WriteTemplatesConfig(); err != nil {
return errkit.Append(errkit.New("failed to write templates config"), err)
return errorutil.NewWithErr(err).Msgf("failed to write templates config")
}
// update ignore hash after writing new templates
if err := config.DefaultConfig.UpdateNucleiIgnoreHash(); err != nil {
return errkit.Append(errkit.New("failed to update nuclei ignore hash"), err)
return errorutil.NewWithErr(err).Msgf("failed to update nuclei ignore hash")
}
// update templates version in config file
if err := config.DefaultConfig.SetTemplatesVersion(ghrd.Latest.GetTagName()); err != nil {
return errkit.Append(errkit.New("failed to update templates version"), err)
return errorutil.NewWithErr(err).Msgf("failed to update templates version")
}
PurgeEmptyDirectories(dir)
@@ -348,11 +324,11 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo
index, err := config.GetNucleiTemplatesIndex()
if err != nil {
return errkit.Append(errkit.New("failed to get nuclei templates index"), err)
return errorutil.NewWithErr(err).Msgf("failed to get nuclei templates index")
}
if err = config.DefaultConfig.WriteTemplatesIndex(index); err != nil {
return errkit.Append(errkit.New("failed to write nuclei templates index"), err)
return errorutil.NewWithErr(err).Msgf("failed to write nuclei templates index")
}
if !HideReleaseNotes {
@@ -448,8 +424,5 @@ func (t *TemplateManager) calculateChecksumMap(dir string) (map[string]string, e
}
return nil
})
if err != nil {
return nil, errkit.Append(errkit.New("failed to calculate checksums of templates"), err)
}
return checksumMap, nil
return checksumMap, errorutil.WrapfWithNil(err, "failed to calculate checksums of templates")
}
-39
View File
@@ -59,42 +59,3 @@ func TestTemplateInstallation(t *testing.T) {
require.FileExists(t, config.DefaultConfig.GetIgnoreFilePath())
t.Logf("Installed %d templates", counter)
}
func TestIsOutdatedVersion(t *testing.T) {
testCases := []struct {
current string
latest string
expected bool
desc string
}{
// Test the empty latest version case (main bug fix)
{"v10.2.7", "", false, "Empty latest version should not trigger update"},
// Test same versions
{"v10.2.7", "v10.2.7", false, "Same versions should not trigger update"},
// Test outdated version
{"v10.2.6", "v10.2.7", true, "Older version should trigger update"},
// Test newer current version (edge case)
{"v10.2.8", "v10.2.7", false, "Newer current version should not trigger update"},
// Test dev versions
{"v10.2.7-dev", "v10.2.7", false, "Dev version matching release should not trigger update"},
{"v10.2.6-dev", "v10.2.7", true, "Outdated dev version should trigger update"},
// Test invalid semver fallback
{"invalid-version", "v10.2.7", true, "Invalid current version should trigger update (fallback)"},
{"v10.2.7", "invalid-version", true, "Invalid latest version should trigger update (fallback)"},
{"same-invalid", "same-invalid", false, "Same invalid versions should not trigger update (fallback)"},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
result := config.IsOutdatedVersion(tc.current, tc.latest)
require.Equal(t, tc.expected, result,
"IsOutdatedVersion(%q, %q) = %t, expected %t",
tc.current, tc.latest, result, tc.expected)
})
}
}
+2 -2
View File
@@ -14,7 +14,7 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
// GetNewTemplatesInVersions returns templates path of all newly added templates
@@ -52,7 +52,7 @@ func getNewAdditionsFileFromGitHub(version string) ([]string, error) {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errkit.New("version not found").Build()
return nil, errorutil.New("version not found")
}
data, err := io.ReadAll(resp.Body)
if err != nil {
+4 -4
View File
@@ -6,7 +6,7 @@ import (
"regexp"
"strings"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
// scrape.go scrapes all information of exported type from different package
@@ -21,17 +21,17 @@ func (p *EntityParser) scrapeAndCreate(typeName string) error {
// get package
pkg, ok := p.imports[pkgName]
if !ok {
return errkit.New(fmt.Sprintf("package %v for type %v not found", pkgName, typeName)).Build()
return errorutil.New("package %v for type %v not found", pkgName, typeName)
}
// get type
obj := pkg.Types.Scope().Lookup(baseTypeName)
if obj == nil {
return errkit.New(fmt.Sprintf("type %v not found in package %+v", typeName, pkg)).Build()
return errorutil.New("type %v not found in package %+v", typeName, pkg)
}
// Ensure the object is a type name
typeNameObj, ok := obj.(*types.TypeName)
if !ok {
return errkit.New(fmt.Sprintf("%v is not a type name", typeName)).Build()
return errorutil.New("%v is not a type name", typeName)
}
// Ensure the type is a named struct type
namedStruct, ok := typeNameObj.Type().Underlying().(*types.Struct)
+2 -2
View File
@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"embed"
"fmt"
"math/rand"
"net"
"reflect"
@@ -18,6 +17,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
)
@@ -257,7 +257,7 @@ func RegisterNativeScripts(runtime *goja.Runtime) error {
// import default modules
_, err = runtime.RunString(defaultImports)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not import default modules %v", defaultImports)), err)
return errorutil.NewWithErr(err).Msgf("could not import default modules %v", defaultImports)
}
return nil
+4 -5
View File
@@ -2,16 +2,15 @@ package gojs
import (
"context"
"fmt"
"reflect"
"github.com/Mzack9999/goja"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
var (
ErrInvalidFuncOpts = errkit.New("invalid function options: %v").Build()
ErrNilRuntime = errkit.New("runtime is nil").Build()
ErrInvalidFuncOpts = errorutil.NewWithFmt("invalid function options: %v")
ErrNilRuntime = errorutil.New("runtime is nil")
)
type FuncOpts struct {
@@ -84,7 +83,7 @@ func RegisterFuncWithSignature(runtime *goja.Runtime, opts FuncOpts) error {
return ErrNilRuntime
}
if !opts.valid() {
return errkit.New(fmt.Sprintf("invalid function options: name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description)).Build()
return ErrInvalidFuncOpts.Msgf("name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description)
}
// Wrap the function with context injection
+3 -3
View File
@@ -63,7 +63,7 @@ func connect(executionId string, host string, port int, username string, passwor
}
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
target := net.JoinHostPort(host, fmt.Sprintf("%d", port))
@@ -118,7 +118,7 @@ func (c *MSSQLClient) IsMssql(ctx context.Context, host string, port int) (bool,
func isMssql(executionId string, host string, port int) (bool, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
dialer := protocolstate.GetDialersWithId(executionId)
@@ -162,7 +162,7 @@ func (c *MSSQLClient) ExecuteQuery(ctx context.Context, host string, port int, u
}
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied(host)
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
target := net.JoinHostPort(host, fmt.Sprintf("%d", port))
+4 -4
View File
@@ -45,7 +45,7 @@ func (c *MySQLClient) IsMySQL(ctx context.Context, host string, port int) (bool,
func isMySQL(executionId string, host string, port int) (bool, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
dialer := protocolstate.GetDialersWithId(executionId)
if dialer == nil {
@@ -85,7 +85,7 @@ func (c *MySQLClient) Connect(ctx context.Context, host string, port int, userna
executionId := ctx.Value("executionId").(string)
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
// executing queries implies the remote mysql service
@@ -144,7 +144,7 @@ func fingerprintMySQL(executionId string, host string, port int) (MySQLInfo, err
info := MySQLInfo{}
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return info, protocolstate.ErrHostDenied(host)
return info, protocolstate.ErrHostDenied.Msgf(host)
}
dialer := protocolstate.GetDialersWithId(executionId)
if dialer == nil {
@@ -209,7 +209,7 @@ func (c *MySQLClient) ExecuteQueryWithOpts(ctx context.Context, opts MySQLOption
executionId := ctx.Value("executionId").(string)
if !protocolstate.IsHostAllowed(executionId, opts.Host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied(opts.Host)
return nil, protocolstate.ErrHostDenied.Msgf(opts.Host)
}
// executing queries implies the remote mysql service
+3 -3
View File
@@ -10,7 +10,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"github.com/projectdiscovery/utils/reader"
)
@@ -201,7 +201,7 @@ func (c *NetConn) RecvFull(N int) ([]byte, error) {
}
bin, err := reader.ConnReadNWithTimeout(c.conn, int64(N), c.timeout)
if err != nil {
return []byte{}, errkit.Append(errkit.New(fmt.Sprintf("failed to read %d bytes", N)), err)
return []byte{}, errorutil.NewWithErr(err).Msgf("failed to read %d bytes", N)
}
return bin, nil
}
@@ -226,7 +226,7 @@ func (c *NetConn) Recv(N int) ([]byte, error) {
b := make([]byte, N)
n, err := c.conn.Read(b)
if err != nil {
return []byte{}, errkit.Append(errkit.New(fmt.Sprintf("failed to read %d bytes", N)), err)
return []byte{}, errorutil.NewWithErr(err).Msgf("failed to read %d bytes", N)
}
return b[:n], nil
}
+2 -2
View File
@@ -122,7 +122,7 @@ func (c *PGClient) ExecuteQuery(ctx context.Context, host string, port int, user
func executeQuery(executionId string, host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied(host)
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
target := net.JoinHostPort(host, fmt.Sprintf("%d", port))
@@ -179,7 +179,7 @@ func connect(executionId string, host string, port int, username string, passwor
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
target := net.JoinHostPort(host, fmt.Sprintf("%d", port))
+4 -4
View File
@@ -27,7 +27,7 @@ func GetServerInfo(ctx context.Context, host string, port int) (string, error) {
func getServerInfo(executionId string, host string, port int) (string, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return "", protocolstate.ErrHostDenied(host)
return "", protocolstate.ErrHostDenied.Msgf(host)
}
// create a new client
client := redis.NewClient(&redis.Options{
@@ -69,7 +69,7 @@ func Connect(ctx context.Context, host string, port int, password string) (bool,
func connect(executionId string, host string, port int, password string) (bool, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
// create a new client
client := redis.NewClient(&redis.Options{
@@ -109,7 +109,7 @@ func GetServerInfoAuth(ctx context.Context, host string, port int, password stri
func getServerInfoAuth(executionId string, host string, port int, password string) (string, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return "", protocolstate.ErrHostDenied(host)
return "", protocolstate.ErrHostDenied.Msgf(host)
}
// create a new client
client := redis.NewClient(&redis.Options{
@@ -181,7 +181,7 @@ func RunLuaScript(ctx context.Context, host string, port int, password string, s
executionId := ctx.Value("executionId").(string)
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
// create a new client
client := redis.NewClient(&redis.Options{
+3 -3
View File
@@ -43,7 +43,7 @@ func (c *SMBClient) ConnectSMBInfoMode(ctx context.Context, host string, port in
func connectSMBInfoMode(executionId string, host string, port int) (*smb.SMBLog, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied(host)
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
dialer := protocolstate.GetDialersWithId(executionId)
if dialer == nil {
@@ -90,7 +90,7 @@ func (c *SMBClient) ListSMBv2Metadata(ctx context.Context, host string, port int
executionId := ctx.Value("executionId").(string)
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied(host)
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
return memoizedcollectSMBv2Metadata(executionId, host, port, 5*time.Second)
}
@@ -119,7 +119,7 @@ func (c *SMBClient) ListShares(ctx context.Context, host string, port int, user,
func listShares(executionId string, host string, port int, user string, password string) ([]string, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied(host)
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
dialer := protocolstate.GetDialersWithId(executionId)
if dialer == nil {
+1 -1
View File
@@ -35,7 +35,7 @@ func (c *SMBClient) DetectSMBGhost(ctx context.Context, host string, port int) (
func detectSMBGhost(executionId string, host string, port int) (bool, error) {
if !protocolstate.IsHostAllowed(executionId, host) {
// host is not valid according to network policy
return false, protocolstate.ErrHostDenied(host)
return false, protocolstate.ErrHostDenied.Msgf(host)
}
addr := net.JoinHostPort(host, strconv.Itoa(port))
dialer := protocolstate.GetDialersWithId(executionId)
+1 -1
View File
@@ -68,7 +68,7 @@ func NewSMTPClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Objec
executionId := c.nj.ExecutionId()
// check if this is allowed address
c.nj.Require(protocolstate.IsHostAllowed(executionId, host+":"+port), protocolstate.ErrHostDenied(host+":"+port).Error())
c.nj.Require(protocolstate.IsHostAllowed(executionId, host+":"+port), protocolstate.ErrHostDenied.Msgf(host+":"+port).Error())
// Link Constructor to Client and return
return utils.LinkConstructor(call, runtime, c)
+5 -5
View File
@@ -7,7 +7,7 @@ import (
"time"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
"github.com/zmap/zgrab2/lib/ssh"
)
@@ -129,7 +129,7 @@ func (c *SSHClient) ConnectSSHInfoMode(ctx context.Context, host string, port in
// ```
func (c *SSHClient) Run(cmd string) (string, error) {
if c.connection == nil {
return "", errkit.New("no connection").Build()
return "", errorutil.New("no connection")
}
session, err := c.connection.NewSession()
if err != nil {
@@ -177,14 +177,14 @@ type connectOptions struct {
func (c *connectOptions) validate() error {
if c.Host == "" {
return errkit.New("host is required").Build()
return errorutil.New("host is required")
}
if c.Port <= 0 {
return errkit.New("port is required").Build()
return errorutil.New("port is required")
}
if !protocolstate.IsHostAllowed(c.ExecutionId, c.Host) {
// host is not valid according to network policy
return protocolstate.ErrHostDenied(c.Host)
return protocolstate.ErrHostDenied.Msgf(c.Host)
}
if c.Timeout == 0 {
c.Timeout = 10 * time.Second
+2 -3
View File
@@ -61,12 +61,11 @@ func init() {
return nil, fmt.Errorf("invalid dns type")
}
options := &types.Options{}
err := dnsclientpool.Init(options)
err := dnsclientpool.Init(&types.Options{})
if err != nil {
return nil, err
}
dnsClient, err := dnsclientpool.Get(options, &dnsclientpool.Configuration{})
dnsClient, err := dnsclientpool.Get(nil, &dnsclientpool.Configuration{})
if err != nil {
return nil, err
}
+2 -13
View File
@@ -5,15 +5,10 @@ import (
"testing"
"github.com/Knetic/govaluate"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/dns/dnsclientpool"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/stretchr/testify/require"
)
func TestDslExpressions(t *testing.T) {
// Use Google DNS for more reliable testing
googleDNS := []string{"8.8.8.8:53", "8.8.4.4:53"}
dslExpressions := map[string]interface{}{
`resolve("scanme.sh")`: "128.199.158.128",
`resolve("scanme.sh","a")`: "128.199.158.128",
@@ -22,7 +17,7 @@ func TestDslExpressions(t *testing.T) {
`resolve("scanme.sh","soa")`: "ns69.domaincontrol.com",
}
testDslExpressionScenariosWithDNS(t, dslExpressions, googleDNS)
testDslExpressionScenarios(t, dslExpressions)
}
func evaluateExpression(t *testing.T, dslExpression string) interface{} {
@@ -39,13 +34,7 @@ func evaluateExpression(t *testing.T, dslExpression string) interface{} {
return actualResult
}
func testDslExpressionScenariosWithDNS(t *testing.T, dslExpressions map[string]interface{}, resolvers []string) {
// Initialize DNS client pool with custom resolvers for testing
err := dnsclientpool.Init(&types.Options{
InternalResolversList: resolvers,
})
require.NoError(t, err, "Failed to initialize DNS client pool with custom resolvers")
func testDslExpressionScenarios(t *testing.T, dslExpressions map[string]interface{}) {
for dslExpression, expectedResult := range dslExpressions {
t.Run(dslExpression, func(t *testing.T) {
actualResult := evaluateExpression(t, dslExpression)
+1 -5
View File
@@ -53,12 +53,8 @@ func NewWafDetector() *WafDetector {
}
func (d *WafDetector) DetectWAF(content string) (string, bool) {
if d == nil || d.regexCache == nil {
return "", false
}
for id, regex := range d.regexCache {
if regex != nil && regex.MatchString(content) {
if regex.MatchString(content) {
return id, true
}
}
+1 -62
View File
@@ -1,9 +1,6 @@
package waf
import (
"regexp"
"testing"
)
import "testing"
func TestWAFDetection(t *testing.T) {
detector := NewWafDetector()
@@ -61,61 +58,3 @@ func TestWAFDetection(t *testing.T) {
})
}
}
func TestWAFDetectionNilPointerSafety(t *testing.T) {
tests := []struct {
name string
detector *WafDetector
content string
}{
{
name: "nil detector",
detector: nil,
content: "test content",
},
{
name: "nil regexCache",
detector: &WafDetector{
wafs: make(map[string]waf),
regexCache: nil,
},
content: "test content",
},
{
name: "regexCache with nil regex",
detector: &WafDetector{
wafs: make(map[string]waf),
regexCache: map[string]*regexp.Regexp{
"test": nil,
},
},
content: "test content",
},
{
name: "empty regexCache",
detector: &WafDetector{
wafs: make(map[string]waf),
regexCache: make(map[string]*regexp.Regexp),
},
content: "test content",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Errorf("DetectWAF panicked with nil pointer: %v", r)
}
}()
waf, matched := tt.detector.DetectWAF(tt.content)
if matched {
t.Errorf("expected no match for nil pointer case, got match=true, waf=%s", waf)
}
if waf != "" {
t.Errorf("expected empty WAF string for nil pointer case, got waf=%s", waf)
}
})
}
}
+4 -3
View File
@@ -33,6 +33,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types"
contextutil "github.com/projectdiscovery/utils/context"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
const (
@@ -113,7 +114,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
if options.Options.Validate {
options.Logger.Error().Msgf("%s <- %s", errMsg, err)
} else {
return errkit.Append(errkit.New(errMsg), err)
return errorutil.NewWithErr(err).Msgf(errMsg)
}
} else {
request.gozero = engine
@@ -153,7 +154,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
if request.PreCondition != "" {
preConditionCompiled, err := compiler.SourceAutoMode(request.PreCondition, false)
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not compile pre-condition: %s", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not compile pre-condition: %s", err)
}
request.preConditionCompiled = preConditionCompiled
}
@@ -230,7 +231,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
Context: input.Context(),
})
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not execute pre-condition: %s", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err)
}
if !result.GetSuccess() || types.ToString(result["error"]) != "" {
gologger.Warning().Msgf("[%s] Precondition for request %s was not satisfied\n", request.TemplateID, request.PreCondition)
@@ -22,7 +22,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/writer"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
)
@@ -88,7 +88,7 @@ func (c *Client) poll() error {
KeepAliveInterval: time.Minute,
})
if err != nil {
return errkit.Append(errkit.New("could not create client"), err)
return errorutil.NewWithErr(err).Msgf("could not create client")
}
c.interactsh = interactsh
@@ -109,7 +109,7 @@ func (c *Client) poll() error {
// If we don't have any request for this ID, add it to temporary
// lru cache, so we can correlate when we get an add request.
items, err := c.interactions.Get(interaction.UniqueID)
if errors.Is(err, gcache.KeyNotFoundError) || items == nil {
if errorutil.IsAny(err, gcache.KeyNotFoundError) || items == nil {
_ = c.interactions.SetWithExpire(interaction.UniqueID, []*server.Interaction{interaction}, defaultInteractionDuration)
} else {
items = append(items, interaction)
@@ -128,7 +128,7 @@ func (c *Client) poll() error {
})
if err != nil {
return errkit.Append(errkit.New("could not perform interactsh polling"), err)
return errorutil.NewWithErr(err).Msgf("could not perform interactsh polling")
}
return nil
}
@@ -239,7 +239,7 @@ func (c *Client) URL() (string, error) {
err = c.poll()
})
if err != nil {
return "", errkit.Append(ErrInteractshClientNotInitialized, err)
return "", errorutil.NewWithErr(err).Wrap(ErrInteractshClientNotInitialized)
}
if c.interactsh == nil {
+3 -4
View File
@@ -1,12 +1,11 @@
package protocolstate
import (
"fmt"
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
mapsutil "github.com/projectdiscovery/utils/maps"
)
@@ -68,12 +67,12 @@ func NormalizePath(options *types.Options, filePath string) (string, error) {
}
cleaned, err := fileutil.ResolveNClean(filePath, config.DefaultConfig.GetTemplateDir())
if err != nil {
return "", errkit.Append(errkit.New(fmt.Sprintf("could not resolve and clean path %v", filePath)), err)
return "", errorutil.NewWithErr(err).Msgf("could not resolve and clean path %v", filePath)
}
// only allow files inside nuclei-templates directory
// even current working directory is not allowed
if strings.HasPrefix(cleaned, config.DefaultConfig.GetTemplateDir()) {
return cleaned, nil
}
return "", errkit.New(fmt.Sprintf("path %v is outside nuclei-template directory and -lfa is not enabled", filePath)).Build()
return "", errorutil.New("path %v is outside nuclei-template directory and -lfa is not enabled", filePath)
}
+8 -14
View File
@@ -2,7 +2,6 @@ package protocolstate
import (
"context"
"fmt"
"net"
"strings"
@@ -10,7 +9,7 @@ import (
"github.com/go-rod/rod/lib/proto"
"github.com/projectdiscovery/networkpolicy"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
urlutil "github.com/projectdiscovery/utils/url"
"go.uber.org/multierr"
@@ -18,15 +17,10 @@ import (
// initialize state of headless protocol
// ErrURLDenied returns an error when a URL is denied by network policy
func ErrURLDenied(url, rule string) error {
return errkit.New(fmt.Sprintf("headless: url %v dropped by rule: %v", url, rule)).Build()
}
// ErrHostDenied returns an error when a host is denied by network policy
func ErrHostDenied(host string) error {
return errkit.New(fmt.Sprintf("host %v dropped by network policy", host)).Build()
}
var (
ErrURLDenied = errorutil.NewWithFmt("headless: url %v dropped by rule: %v")
ErrHostDenied = errorutil.NewWithFmt("host %v dropped by network policy")
)
func GetNetworkPolicy(ctx context.Context) *networkpolicy.NetworkPolicy {
execCtx := GetExecutionContext(ctx)
@@ -47,15 +41,15 @@ func ValidateNFailRequest(options *types.Options, page *rod.Page, e *proto.Fetch
normalized := strings.ToLower(reqURL) // normalize url to lowercase
normalized = strings.TrimSpace(normalized) // trim leading & trailing whitespaces
if !IsLfaAllowed(options) && stringsutil.HasPrefixI(normalized, "file:") {
return multierr.Combine(FailWithReason(page, e), ErrURLDenied(reqURL, "use of file:// protocol disabled use '-lfa' to enable"))
return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "use of file:// protocol disabled use '-lfa' to enable"))
}
// validate potential invalid schemes
// javascript protocol is allowed for xss fuzzing
if stringsutil.HasPrefixAnyI(normalized, "ftp:", "externalfile:", "chrome:", "chrome-extension:") {
return multierr.Combine(FailWithReason(page, e), ErrURLDenied(reqURL, "protocol blocked by network policy"))
return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "protocol blocked by network policy"))
}
if !isValidHost(options, reqURL) {
return multierr.Combine(FailWithReason(page, e), ErrURLDenied(reqURL, "address blocked by network policy"))
return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "address blocked by network policy"))
}
return nil
}
+7 -41
View File
@@ -20,13 +20,12 @@ import (
// Browser is a browser structure for nuclei headless module
type Browser struct {
customAgent string
defaultHeaders map[string]string
tempDir string
previousPIDs map[int32]struct{} // track already running PIDs
engine *rod.Browser
options *types.Options
launcher *launcher.Launcher
customAgent string
tempDir string
previousPIDs map[int32]struct{} // track already running PIDs
engine *rod.Browser
options *types.Options
launcher *launcher.Launcher
// use getHTTPClient to get the http client
httpClient *http.Client
@@ -96,7 +95,6 @@ func New(options *types.Options) (*Browser, error) {
if browserErr := browser.Connect(); browserErr != nil {
return nil, browserErr
}
defaultHeaders := make(map[string]string)
customAgent := ""
for _, option := range options.CustomHeaders {
parts := strings.SplitN(option, ":", 2)
@@ -105,20 +103,12 @@ func New(options *types.Options) (*Browser, error) {
}
if strings.EqualFold(parts[0], "User-Agent") {
customAgent = parts[1]
} else {
k := strings.TrimSpace(parts[0])
v := strings.TrimSpace(parts[1])
if k == "" || v == "" {
continue
}
defaultHeaders[k] = v
}
}
engine := &Browser{
tempDir: dataStore,
customAgent: customAgent,
defaultHeaders: defaultHeaders,
engine: browser,
options: options,
httpClientOnce: &sync.Once{},
@@ -145,30 +135,6 @@ func (b *Browser) UserAgent() string {
return b.customAgent
}
// applyDefaultHeaders setsheaders passed via cli -H flag
func (b *Browser) applyDefaultHeaders(p *rod.Page) error {
pairs := make([]string, 0, len(b.defaultHeaders)*2+2)
hasAcceptLanguage := false
for k := range b.defaultHeaders {
if strings.EqualFold(k, "Accept-Language") {
hasAcceptLanguage = true
break
}
}
if !hasAcceptLanguage {
pairs = append(pairs, "Accept-Language", "en, en-GB, en-us;")
}
for k, v := range b.defaultHeaders {
pairs = append(pairs, k, v)
}
if len(pairs) == 0 {
return nil
}
_, err := p.SetExtraHeaders(pairs)
return err
}
func (b *Browser) getHTTPClient() (*http.Client, error) {
var err error
b.httpClientOnce.Do(func() {
@@ -181,6 +147,6 @@ func (b *Browser) getHTTPClient() (*http.Client, error) {
func (b *Browser) Close() {
_ = b.engine.Close()
b.launcher.Kill()
_ = os.RemoveAll(b.tempDir)
os.RemoveAll(b.tempDir)
processutil.CloseProcesses(processutil.IsChromeProcess, b.previousPIDs)
}
+6 -6
View File
@@ -18,7 +18,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
httputil "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils/http"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
urlutil "github.com/projectdiscovery/utils/url"
)
@@ -61,10 +61,6 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map
}
page = page.Timeout(options.Timeout)
if err = i.browser.applyDefaultHeaders(page); err != nil {
return nil, nil, err
}
if i.browser.customAgent != "" {
if userAgentErr := page.SetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: i.browser.customAgent}); userAgentErr != nil {
return nil, nil, userAgentErr
@@ -78,7 +74,7 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map
target := ctx.MetaInput.Input
input, err := urlutil.Parse(target)
if err != nil {
return nil, nil, errkit.Append(errkit.New(fmt.Sprintf("could not parse URL %s", target)), err)
return nil, nil, errorutil.NewWithErr(err).Msgf("could not parse URL %s", target)
}
hasTrailingSlash := httputil.HasTrailingSlash(target)
@@ -134,6 +130,10 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map
return nil, nil, err
}
if _, err := page.SetExtraHeaders([]string{"Accept-Language", "en, en-GB, en-us;"}); err != nil {
return nil, nil, err
}
// inject cookies
// each http request is performed via the native go http client
// we first inject the shared cookies
+14 -13
View File
@@ -23,6 +23,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
contextutil "github.com/projectdiscovery/utils/context"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
folderutil "github.com/projectdiscovery/utils/folder"
stringsutil "github.com/projectdiscovery/utils/strings"
@@ -31,8 +32,8 @@ import (
)
var (
errinvalidArguments = errkit.New("invalid arguments provided").Build()
ErrLFAccessDenied = errkit.New("Use -allow-local-file-access flag to enable local file access").Build()
errinvalidArguments = errorutil.New("invalid arguments provided")
ErrLFAccessDenied = errorutil.New("Use -allow-local-file-access flag to enable local file access")
// ErrActionExecDealine is the error returned when alloted time for action execution exceeds
ErrActionExecDealine = errkit.New("headless action execution deadline exceeded").SetKind(errkit.ErrKindDeadline).Build()
)
@@ -59,7 +60,7 @@ func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action) (ou
}
if r := recover(); r != nil {
err = errkit.New(fmt.Sprintf("panic on headless action: %v", r)).Build()
err = errorutil.New("panic on headless action: %v", r)
}
}()
@@ -72,7 +73,7 @@ func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action) (ou
for _, waitFunc := range waitFuncs {
if waitFunc != nil {
if err := waitFunc(); err != nil {
return nil, errkit.Append(errkit.New("error occurred while executing waitFunc"), err)
return nil, errorutil.NewWithErr(err).Msgf("error occurred while executing waitFunc")
}
}
}
@@ -400,7 +401,7 @@ func (p *Page) NavigateURL(action *Action, out ActionData) error {
parsedURL, err := urlutil.ParseURL(url, true)
if err != nil {
return errkit.New(fmt.Sprintf("headless: failed to parse url %v while creating http request", url)).Build()
return errorutil.NewWithTag("headless", "failed to parse url %v while creating http request", url)
}
// ===== parameter automerge =====
@@ -410,7 +411,7 @@ func (p *Page) NavigateURL(action *Action, out ActionData) error {
parsedURL.Params = finalparams
if err := p.page.Navigate(parsedURL.String()); err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not navigate to url %s", parsedURL.String())), err)
return errorutil.NewWithErr(err).Msgf("could not navigate to url %s", parsedURL.String())
}
p.updateLastNavigatedURL()
@@ -524,14 +525,14 @@ func (p *Page) Screenshot(act *Action, out ActionData) error {
to, err = fileutil.CleanPath(to)
if err != nil {
return errkit.New(fmt.Sprintf("could not clean output screenshot path %s", to)).Build()
return errorutil.New("could not clean output screenshot path %s", to)
}
// allow if targetPath is child of current working directory
if !protocolstate.IsLfaAllowed(p.options.Options) {
cwd, err := os.Getwd()
if err != nil {
return errkit.Append(errkit.New("could not get current working directory"), err)
return errorutil.NewWithErr(err).Msgf("could not get current working directory")
}
if !strings.HasPrefix(to, cwd) {
@@ -550,7 +551,7 @@ func (p *Page) Screenshot(act *Action, out ActionData) error {
// creates new directory if needed based on path `to`
// TODO: replace all permission bits with fileutil constants (https://github.com/projectdiscovery/utils/issues/113)
if err := os.MkdirAll(filepath.Dir(to), 0700); err != nil {
return errkit.Append(errkit.New("failed to create directory while writing screenshot"), err)
return errorutil.NewWithErr(err).Msgf("failed to create directory while writing screenshot")
}
}
@@ -562,7 +563,7 @@ func (p *Page) Screenshot(act *Action, out ActionData) error {
if fileutil.FileExists(filePath) {
// return custom error as overwriting files is not supported
return errkit.New(fmt.Sprintf("screenshot: failed to write screenshot, file %v already exists", filePath)).Build()
return errorutil.NewWithTag("screenshot", "failed to write screenshot, file %v already exists", filePath)
}
err = os.WriteFile(filePath, data, 0540)
if err != nil {
@@ -805,12 +806,12 @@ func (p *Page) WaitEvent(act *Action, out ActionData) (func() error, error) {
gotType := proto.GetType(event)
if gotType == nil {
return nil, errkit.New(fmt.Sprintf("event %q does not exist", event)).Build()
return nil, errorutil.New("event %q does not exist", event)
}
tmp, ok := reflect.New(gotType).Interface().(proto.Event)
if !ok {
return nil, errkit.New(fmt.Sprintf("event %q is not a page event", event)).Build()
return nil, errorutil.New("event %q is not a page event", event)
}
waitEvent = tmp
@@ -947,7 +948,7 @@ func (p *Page) getActionArg(action *Action, arg string) (string, error) {
err = expressions.ContainsUnresolvedVariables(exprs...)
if err != nil {
return "", errkit.Append(errkit.New(fmt.Sprintf("argument %q, value: %q", arg, argValue)), err)
return "", errorutil.NewWithErr(err).Msgf("argument %q, value: %q", arg, argValue)
}
argValue, err = expressions.Evaluate(argValue, p.variables)
+19 -25
View File
@@ -27,7 +27,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types/scanstrategy"
"github.com/projectdiscovery/rawhttp"
"github.com/projectdiscovery/retryablehttp-go"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
readerutil "github.com/projectdiscovery/utils/reader"
stringsutil "github.com/projectdiscovery/utils/strings"
urlutil "github.com/projectdiscovery/utils/url"
@@ -37,17 +37,11 @@ const (
ReqURLPatternKey = "req_url_pattern"
)
// ErrEvalExpression returns an error when helper expressions cannot be evaluated
func ErrEvalExpression(tag string) func(error) error {
return func(err error) error {
return errkit.Append(errkit.New(fmt.Sprintf("%s: could not evaluate helper expressions", tag)), err)
}
}
// ErrUnresolvedVars returns an error when unresolved variables are found in request
func ErrUnresolvedVars(vars string) error {
return errkit.New(fmt.Sprintf("unresolved variables `%v` found in request", vars)).Build()
}
// ErrEvalExpression
var (
ErrEvalExpression = errorutil.NewWithTag("expr", "could not evaluate helper expressions")
ErrUnresolvedVars = errorutil.NewWithFmt("unresolved variables `%v` found in request")
)
// generatedRequest is a single generated request wrapped for a template request
type generatedRequest struct {
@@ -199,7 +193,7 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context,
for payloadName, payloadValue := range payloads {
payloads[payloadName], err = expressions.Evaluate(types.ToString(payloadValue), allVars)
if err != nil {
return nil, ErrEvalExpression("http")(err)
return nil, ErrEvalExpression.Wrap(err).WithTag("http")
}
}
// finalVars contains allVars and any generator/fuzzing specific payloads
@@ -216,7 +210,7 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context,
// Evaluate (replace) variable with final values
reqData, err = expressions.Evaluate(reqData, finalVars)
if err != nil {
return nil, ErrEvalExpression("http")(err)
return nil, ErrEvalExpression.Wrap(err).WithTag("http")
}
if isRawRequest {
@@ -225,7 +219,7 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context,
reqURL, err := urlutil.ParseAbsoluteURL(reqData, true)
if err != nil {
return nil, errkit.New(fmt.Sprintf("http: failed to parse url %v while creating http request", reqData)).Build()
return nil, errorutil.NewWithTag("http", "failed to parse url %v while creating http request", reqData)
}
// while merging parameters first preference is given to target params
finalparams := parsed.Params
@@ -258,7 +252,7 @@ func (r *requestGenerator) makeSelfContainedRequest(ctx context.Context, data st
// evaluate request
data, err := expressions.Evaluate(data, values)
if err != nil {
return nil, ErrEvalExpression("self-contained")(err)
return nil, ErrEvalExpression.Wrap(err).WithTag("self-contained")
}
// If the request is a raw request, get the URL from the request
// header and use it to make the request.
@@ -281,7 +275,7 @@ func (r *requestGenerator) makeSelfContainedRequest(ctx context.Context, data st
}
if err := expressions.ContainsUnresolvedVariables(parts[1]); err != nil && !r.request.SkipVariablesCheck {
return nil, ErrUnresolvedVars(parts[1])
return nil, ErrUnresolvedVars.Msgf(parts[1])
}
parsed, err := urlutil.ParseURL(parts[1], true)
@@ -295,19 +289,19 @@ func (r *requestGenerator) makeSelfContainedRequest(ctx context.Context, data st
// Evaluate (replace) variable with final values
data, err = expressions.Evaluate(data, values)
if err != nil {
return nil, ErrEvalExpression("self-contained")(err)
return nil, ErrEvalExpression.Wrap(err).WithTag("self-contained", "raw")
}
return r.generateRawRequest(ctx, data, parsed, values, payloads)
}
if err := expressions.ContainsUnresolvedVariables(data); err != nil && !r.request.SkipVariablesCheck {
// early exit: if there are any unresolved variables in `path` after evaluation
// then return early since this will definitely fail
return nil, ErrUnresolvedVars(data)
return nil, ErrUnresolvedVars.Msgf(data)
}
urlx, err := urlutil.ParseURL(data, true)
if err != nil {
return nil, errkit.New(fmt.Sprintf("self-contained: failed to parse %v in self contained request: %s", data, err)).Build()
return nil, errorutil.NewWithErr(err).Msgf("failed to parse %v in self contained request", data).WithTag("self-contained")
}
return r.generateHttpRequest(ctx, urlx, values, payloads)
}
@@ -318,7 +312,7 @@ func (r *requestGenerator) makeSelfContainedRequest(ctx context.Context, data st
func (r *requestGenerator) generateHttpRequest(ctx context.Context, urlx *urlutil.URL, finalVars, generatorValues map[string]interface{}) (*generatedRequest, error) {
method, err := expressions.Evaluate(r.request.Method.String(), finalVars)
if err != nil {
return nil, ErrEvalExpression("http")(err)
return nil, ErrEvalExpression.Wrap(err).Msgf("failed to evaluate while generating http request")
}
// Build a request on the specified URL
req, err := retryablehttp.NewRequestFromURLWithContext(ctx, method, urlx, nil)
@@ -347,7 +341,7 @@ func (r *requestGenerator) generateRawRequest(ctx context.Context, rawRequest st
rawRequestData, err = raw.Parse(rawRequest, baseURL, r.request.Unsafe, r.request.DisablePathAutomerge)
}
if err != nil {
return nil, errkit.Append(errkit.New("failed to parse raw request"), err)
return nil, errorutil.NewWithErr(err).Msgf("failed to parse raw request")
}
// Unsafe option uses rawhttp library
@@ -363,7 +357,7 @@ func (r *requestGenerator) generateRawRequest(ctx context.Context, rawRequest st
}
urlx, err := urlutil.ParseAbsoluteURL(rawRequestData.FullURL, true)
if err != nil {
return nil, errkit.New(fmt.Sprintf("raw: failed to create request with url %v got %v", rawRequestData.FullURL, err)).Build()
return nil, errorutil.NewWithErr(err).Msgf("failed to create request with url %v got %v", rawRequestData.FullURL, err).WithTag("raw")
}
req, err := retryablehttp.NewRequestFromURLWithContext(ctx, rawRequestData.Method, urlx, rawRequestData.Data)
if err != nil {
@@ -420,7 +414,7 @@ func (r *requestGenerator) fillRequest(req *retryablehttp.Request, values map[st
}
value, err := expressions.Evaluate(value, values)
if err != nil {
return nil, ErrEvalExpression("http")(err)
return nil, ErrEvalExpression.Wrap(err).Msgf("failed to evaluate while adding headers to request")
}
req.Header[header] = []string{value}
if header == "Host" {
@@ -441,7 +435,7 @@ func (r *requestGenerator) fillRequest(req *retryablehttp.Request, values map[st
}
body, err := expressions.Evaluate(body, values)
if err != nil {
return nil, ErrEvalExpression("http")(err)
return nil, ErrEvalExpression.Wrap(err)
}
bodyReader, err := readerutil.NewReusableReadCloser([]byte(body))
if err != nil {
+8 -8
View File
@@ -12,7 +12,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx"
"github.com/projectdiscovery/rawhttp/client"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
urlutil "github.com/projectdiscovery/utils/url"
)
@@ -48,7 +48,7 @@ func Parse(request string, inputURL *urlutil.URL, unsafe, disablePathAutomerge b
case strings.HasPrefix(rawrequest.Path, "http") && !unsafe:
urlx, err := urlutil.ParseURL(rawrequest.Path, true)
if err != nil {
return nil, errkit.New(fmt.Sprintf("raw: failed to parse url %v from template: %s", rawrequest.Path, err)).Build()
return nil, errorutil.NewWithErr(err).WithTag("raw").Msgf("failed to parse url %v from template", rawrequest.Path)
}
cloned := inputURL.Clone()
cloned.Params.IncludeEquals = true
@@ -57,7 +57,7 @@ func Parse(request string, inputURL *urlutil.URL, unsafe, disablePathAutomerge b
}
parseErr := cloned.MergePath(urlx.GetRelativePath(), true)
if parseErr != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("raw: could not automergepath for template path %v", urlx.GetRelativePath())), parseErr)
return nil, errorutil.NewWithTag("raw", "could not automergepath for template path %v", urlx.GetRelativePath()).Wrap(parseErr)
}
rawrequest.Path = cloned.GetRelativePath()
// If unsafe changes must be made in raw request string itself
@@ -94,7 +94,7 @@ func Parse(request string, inputURL *urlutil.URL, unsafe, disablePathAutomerge b
}
err = cloned.MergePath(rawrequest.Path, true)
if err != nil {
return nil, errkit.New(fmt.Sprintf("raw: failed to automerge %v from unsafe template: %s", rawrequest.Path, err)).Build()
return nil, errorutil.NewWithErr(err).WithTag("raw").Msgf("failed to automerge %v from unsafe template", rawrequest.Path)
}
unsafeRelativePath = cloned.GetRelativePath()
}
@@ -116,7 +116,7 @@ func Parse(request string, inputURL *urlutil.URL, unsafe, disablePathAutomerge b
}
parseErr := cloned.MergePath(rawrequest.Path, true)
if parseErr != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("raw: could not automergepath for template path %v", rawrequest.Path)), parseErr)
return nil, errorutil.NewWithTag("raw", "could not automergepath for template path %v", rawrequest.Path).Wrap(parseErr)
}
rawrequest.Path = cloned.GetRelativePath()
}
@@ -145,18 +145,18 @@ func ParseRawRequest(request string, unsafe bool) (*Request, error) {
if strings.HasPrefix(req.Path, "http") {
urlx, err := urlutil.Parse(req.Path)
if err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("failed to parse url %v", req.Path)), err)
return nil, errorutil.NewWithErr(err).Msgf("failed to parse url %v", req.Path)
}
req.Path = urlx.GetRelativePath()
req.FullURL = urlx.String()
} else {
if req.Path == "" {
return nil, errkit.New("self-contained-raw: path cannot be empty in self contained request").Build()
return nil, errorutil.NewWithTag("self-contained-raw", "path cannot be empty in self contained request")
}
// given url is relative construct one using Host Header
if _, ok := req.Headers["Host"]; !ok {
return nil, errkit.New("self-contained-raw: host header is required for relative path").Build()
return nil, errorutil.NewWithTag("self-contained-raw", "host header is required for relative path")
}
// Review: Current default scheme in self contained templates if relative path is provided is http
req.FullURL = fmt.Sprintf("%s://%s%s", urlutil.HTTP, strings.TrimSpace(req.Headers["Host"]), req.Path)
+5 -6
View File
@@ -76,7 +76,7 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, previous
if errors.Is(err, ErrMissingVars) {
return err
}
gologger.Verbose().Msgf("[%s] fuzz: payload request execution failed: %s\n", request.options.TemplateID, err)
gologger.Verbose().Msgf("[%s] fuzz: payload request execution failed : %s\n", request.options.TemplateID, err)
}
return nil
}
@@ -103,13 +103,13 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, previous
// in case of any error, return it
if fuzz.IsErrRuleNotApplicable(err) {
// log and fail silently
gologger.Verbose().Msgf("[%s] fuzz: %s\n", request.options.TemplateID, err)
gologger.Verbose().Msgf("[%s] fuzz: rule not applicable : %s\n", request.options.TemplateID, err)
return nil
}
if errors.Is(err, ErrMissingVars) {
return err
}
gologger.Verbose().Msgf("[%s] fuzz: payload request execution failed: %s\n", request.options.TemplateID, err)
gologger.Verbose().Msgf("[%s] fuzz: payload request execution failed : %s\n", request.options.TemplateID, err)
}
return nil
}
@@ -158,7 +158,7 @@ func (request *Request) executeAllFuzzingRules(input *contextargs.Context, value
continue
}
if fuzz.IsErrRuleNotApplicable(err) {
gologger.Verbose().Msgf("[%s] fuzz: %s\n", request.options.TemplateID, err)
gologger.Verbose().Msgf("[%s] fuzz: rule not applicable : %s\n", request.options.TemplateID, err)
continue
}
if err == types.ErrNoMoreRequests {
@@ -168,9 +168,8 @@ func (request *Request) executeAllFuzzingRules(input *contextargs.Context, value
}
if !applicable {
return fmt.Errorf("no rule was applicable for this request: %v", input.MetaInput.Input)
return fuzz.ErrRuleNotApplicable.Msgf(fmt.Sprintf("no rule was applicable for this request: %v", input.MetaInput.Input))
}
return nil
}
+2 -2
View File
@@ -14,7 +14,7 @@ import (
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
const defaultEmptyPayloadHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
@@ -60,7 +60,7 @@ func (a *AWSSigner) SignHTTP(ctx context.Context, request *http.Request) error {
// contentHash is sha256 hash of response body
contentHash := a.getPayloadHash(request)
if err := a.signer.SignHTTP(ctx, *a.creds, request, contentHash, a.options.Service, a.options.Region, time.Now()); err != nil {
return errkit.Append(errkit.New("failed to sign http request using aws v4 signer"), err)
return errorutil.NewWithErr(err).Msgf("failed to sign http request using aws v4 signer")
}
// add x-amz-content-sha256 header to request
request.Header.Set("x-amz-content-sha256", contentHash)
+3 -4
View File
@@ -1,13 +1,12 @@
package http
import (
"fmt"
"io"
"strings"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
"github.com/projectdiscovery/rawhttp"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
// dump creates a dump of the http request in form of a byte slice
@@ -16,14 +15,14 @@ func dump(req *generatedRequest, reqURL string) ([]byte, error) {
// Use a clone to avoid a race condition with the http transport
bin, err := req.request.Clone(req.request.Context()).Dump()
if err != nil {
return nil, errkit.New(fmt.Sprintf("http: could not dump request: %v: %s", req.request.String(), err)).Build()
return nil, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", req.request.String())
}
return bin, nil
}
rawHttpOptions := &rawhttp.Options{CustomHeaders: req.rawRequest.UnsafeHeaders, CustomRawBytes: req.rawRequest.UnsafeRawBytes}
bin, err := rawhttp.DumpRequestRaw(req.rawRequest.Method, reqURL, req.rawRequest.Path, generators.ExpandMapValues(req.rawRequest.Headers), io.NopCloser(strings.NewReader(req.rawRequest.Data)), rawHttpOptions)
if err != nil {
return nil, errkit.New(fmt.Sprintf("http: could not dump request: %v: %s", reqURL, err)).Build()
return nil, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", reqURL)
}
return bin, nil
}
+7 -6
View File
@@ -34,6 +34,7 @@ import (
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
iputil "github.com/projectdiscovery/utils/ip"
mapsutil "github.com/projectdiscovery/utils/maps"
syncutil "github.com/projectdiscovery/utils/sync"
@@ -127,14 +128,14 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
}
}
if err := compiled.Compile(); err != nil {
return errkit.New(fmt.Sprintf("%s: could not compile operators got %v", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not compile operators got %v", err)
}
request.CompiledOperators = compiled
}
// "Port" is a special variable and it should not contains any dsl expressions
if strings.Contains(request.getPort(), "{{") {
return errkit.New(fmt.Sprintf("%s: 'Port' variable cannot contain any dsl expressions", request.TemplateID)).Build()
return errorutil.NewWithTag(request.TemplateID, "'Port' variable cannot contain any dsl expressions")
}
if request.Init != "" {
@@ -218,11 +219,11 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
initCompiled, err := compiler.SourceAutoMode(request.Init, false)
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not compile init code: %s", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not compile init code: %s", err)
}
result, err := request.options.JsCompiler.ExecuteWithOptions(initCompiled, args, opts)
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not execute pre-condition: %s", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err)
}
if types.ToString(result["error"]) != "" {
gologger.Warning().Msgf("[%s] Init failed with error %v\n", request.TemplateID, result["error"])
@@ -239,7 +240,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
if request.PreCondition != "" {
preConditionCompiled, err := compiler.SourceAutoMode(request.PreCondition, false)
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not compile pre-condition: %s", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not compile pre-condition: %s", err)
}
request.preConditionCompiled = preConditionCompiled
}
@@ -248,7 +249,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
if request.Code != "" {
scriptCompiled, err := compiler.SourceAutoMode(request.Code, false)
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not compile javascript code: %s", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not compile javascript code: %s", err)
}
request.scriptCompiled = scriptCompiled
}
+3 -4
View File
@@ -1,7 +1,6 @@
package network
import (
"fmt"
"strconv"
"strings"
@@ -13,7 +12,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
)
@@ -197,10 +196,10 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
}
portInt, err := strconv.Atoi(port)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("could not parse port %v from '%s'", port, request.Port)), err)
return errorutil.NewWithErr(err).Msgf("could not parse port %v from '%s'", port, request.Port)
}
if portInt < 1 || portInt > 65535 {
return errkit.New(fmt.Sprintf("%s: port %v is not in valid range", request.TemplateID, portInt)).Build()
return errorutil.NewWithTag(request.TemplateID, "port %v is not in valid range", portInt)
}
request.ports = append(request.ports, port)
}
+2 -2
View File
@@ -31,7 +31,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool"
protocolutils "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils"
templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
mapsutil "github.com/projectdiscovery/utils/maps"
"github.com/projectdiscovery/utils/reader"
syncutil "github.com/projectdiscovery/utils/sync"
@@ -362,7 +362,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac
if input.Read > 0 {
buffer, err := ConnReadNWithTimeout(conn, int64(input.Read), request.options.Options.GetTimeouts().TcpReadTimeout)
if err != nil {
return errkit.Append(errkit.New("could not read response from connection"), err)
return errorutil.NewWithErr(err).Msgf("could not read response from connection")
}
responseBuilder.Write(buffer)
+9 -9
View File
@@ -33,7 +33,7 @@ import (
"github.com/projectdiscovery/tlsx/pkg/tlsx"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
"github.com/projectdiscovery/tlsx/pkg/tlsx/openssl"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
)
@@ -121,7 +121,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
CustomDialer: options.CustomFastdialer,
})
if err != nil {
return errkit.Append(errkit.New("ssl: could not get network client"), err)
return errorutil.NewWithTag("ssl", "could not get network client").Wrap(err)
}
request.dialer = client
switch {
@@ -130,7 +130,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
request.ScanMode = "auto"
case !stringsutil.EqualFoldAny(request.ScanMode, "auto", "openssl", "ztls", "ctls"):
return errkit.New(fmt.Sprintf("%s: template %v does not contain valid scan-mode", request.TemplateID, request.TemplateID)).Build()
return errorutil.NewWithTag(request.TemplateID, "template %v does not contain valid scan-mode", request.TemplateID)
case request.ScanMode == "openssl" && !openssl.IsAvailable():
// if openssl is not installed instead of failing "auto" scanmode is used
@@ -169,7 +169,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
tlsxService, err := tlsx.New(tlsxOptions)
if err != nil {
return errkit.New(fmt.Sprintf("%s: could not create tlsx service", request.TemplateID)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not create tlsx service")
}
request.tlsx = tlsxService
@@ -178,7 +178,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
compiled.ExcludeMatchers = options.ExcludeMatchers
compiled.TemplateID = options.TemplateID
if err := compiled.Compile(); err != nil {
return errkit.New(fmt.Sprintf("%s: could not compile operators got %v", request.TemplateID, err)).Build()
return errorutil.NewWithTag(request.TemplateID, "could not compile operators got %v", err)
}
request.CompiledOperators = compiled
}
@@ -236,7 +236,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
addressToDial := string(finalAddress)
host, port, err := net.SplitHostPort(addressToDial)
if err != nil {
return errkit.Append(errkit.New("could not split input host port"), err)
return errorutil.NewWithErr(err).Msgf("could not split input host port")
}
var hostIp string
@@ -250,7 +250,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
if err != nil {
requestOptions.Output.Request(requestOptions.TemplateID, input.MetaInput.Input, request.Type().String(), err)
requestOptions.Progress.IncrementFailedRequestsBy(1)
return errkit.Append(errkit.New(fmt.Sprintf("%s: could not connect to server", request.TemplateID)), err)
return errorutil.NewWithTag(request.TemplateID, "could not connect to server").Wrap(err)
}
requestOptions.Output.Request(requestOptions.TemplateID, hostPort, request.Type().String(), err)
@@ -287,7 +287,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
// if response is not struct compatible, error out
if !structs.IsStruct(response) {
return errkit.New(fmt.Sprintf("ssl: response cannot be parsed into a struct: %v", response)).Build()
return errorutil.NewWithTag("ssl", "response cannot be parsed into a struct: %v", response)
}
// Convert response to key value pairs and first cert chain item as well
@@ -307,7 +307,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
// if certificate response is not struct compatible, error out
if !structs.IsStruct(response.CertificateResponse) {
return errkit.New(fmt.Sprintf("ssl: certificate response cannot be parsed into a struct: %v", response.CertificateResponse)).Build()
return errorutil.NewWithTag("ssl", "certificate response cannot be parsed into a struct: %v", response.CertificateResponse)
}
responseParsed = structs.New(response.CertificateResponse)
@@ -5,7 +5,7 @@ import (
"fmt"
"strings"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
func CreateLink(title string, url string) string {
@@ -20,7 +20,7 @@ func CreateTable(headers []string, rows [][]string) (string, error) {
builder := &bytes.Buffer{}
headerSize := len(headers)
if headers == nil || headerSize == 0 {
return "", errkit.New("No headers provided").Build()
return "", errorutil.New("No headers provided")
}
builder.WriteString(CreateTableHeader(headers...))
@@ -34,7 +34,7 @@ func CreateTable(headers []string, rows [][]string) (string, error) {
copy(extendedRows, row)
builder.WriteString(CreateTableRow(extendedRows...))
} else {
return "", errkit.New("Too many columns for the given headers").Build()
return "", errorutil.New("Too many columns for the given headers")
}
}
+14 -14
View File
@@ -31,7 +31,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/gitlab"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/jira"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/linear"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
)
@@ -84,7 +84,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.GitHub.OmitRaw = options.OmitRaw
tracker, err := github.New(options.GitHub)
if err != nil {
return nil, errkit.Append(ErrReportingClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation)
}
client.trackers = append(client.trackers, tracker)
}
@@ -93,7 +93,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.GitLab.OmitRaw = options.OmitRaw
tracker, err := gitlab.New(options.GitLab)
if err != nil {
return nil, errkit.Append(ErrReportingClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation)
}
client.trackers = append(client.trackers, tracker)
}
@@ -102,7 +102,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.Gitea.OmitRaw = options.OmitRaw
tracker, err := gitea.New(options.Gitea)
if err != nil {
return nil, errkit.Append(ErrReportingClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation)
}
client.trackers = append(client.trackers, tracker)
}
@@ -111,7 +111,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.Jira.OmitRaw = options.OmitRaw
tracker, err := jira.New(options.Jira)
if err != nil {
return nil, errkit.Append(ErrReportingClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation)
}
client.trackers = append(client.trackers, tracker)
}
@@ -120,35 +120,35 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.Linear.OmitRaw = options.OmitRaw
tracker, err := linear.New(options.Linear)
if err != nil {
return nil, errkit.Append(ErrReportingClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation)
}
client.trackers = append(client.trackers, tracker)
}
if options.MarkdownExporter != nil {
exporter, err := markdown.New(options.MarkdownExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
if options.SarifExporter != nil {
exporter, err := sarif.New(options.SarifExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
if options.JSONExporter != nil {
exporter, err := json_exporter.New(options.JSONExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
if options.JSONLExporter != nil {
exporter, err := jsonl.New(options.JSONLExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
@@ -157,7 +157,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.ElasticsearchExporter.ExecutionId = options.ExecutionId
exporter, err := es.New(options.ElasticsearchExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
@@ -166,14 +166,14 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) {
options.SplunkExporter.ExecutionId = options.ExecutionId
exporter, err := splunk.New(options.SplunkExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
if options.MongoDBExporter != nil {
exporter, err := mongo.New(options.MongoDBExporter)
if err != nil {
return nil, errkit.Append(ErrExportClientCreation, err)
return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation)
}
client.exporters = append(client.exporters, exporter)
}
@@ -227,7 +227,7 @@ func CreateConfigIfNotExists() error {
}
reportingFile, err := os.Create(reportingConfig)
if err != nil {
return errkit.Append(errkit.New("could not create config file"), err)
return errorutil.NewWithErr(err).Msgf("could not create config file")
}
defer func() {
_ = reportingFile.Close()
+1 -1
View File
@@ -54,7 +54,7 @@ type Options struct {
// New creates a new issue tracker integration client based on options.
func New(options *Options) (*Integration, error) {
var transport = http.DefaultTransport
var transport http.RoundTripper = http.DefaultTransport
if options.HttpClient != nil && options.HttpClient.HTTPClient.Transport != nil {
transport = options.HttpClient.HTTPClient.Transport
}
+1 -1
View File
@@ -25,7 +25,7 @@ type ScanStatsWorker struct {
m *sync.Mutex
directory string
file *os.File
enc json.Encoder
enc *json.Encoder
}
// Init initializes the scan stats worker
+3 -3
View File
@@ -25,7 +25,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/tmplexec"
"github.com/projectdiscovery/nuclei/v3/pkg/utils"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
stringsutil "github.com/projectdiscovery/utils/strings"
)
@@ -480,7 +480,7 @@ func parseTemplate(data []byte, srcOptions *protocols.ExecutorOptions) (*Templat
}
}
if err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("failed to parse %s", template.Path)), err)
return nil, errorutil.NewWithErr(err).Msgf("failed to parse %s", template.Path)
}
if utils.IsBlank(template.Info.Name) {
@@ -540,7 +540,7 @@ func parseTemplate(data []byte, srcOptions *protocols.ExecutorOptions) (*Templat
// load `flow` and `source` in code protocol from file
// if file is referenced instead of actual source code
if err := template.ImportFileRefs(template.Options); err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("failed to load file refs for %s", template.ID)), err)
return nil, errorutil.NewWithErr(err).Msgf("failed to load file refs for %s", template.ID)
}
if err := template.compileProtocolRequests(template.Options); err != nil {
+4 -4
View File
@@ -82,7 +82,7 @@ func (p *Parser) LoadTemplate(templatePath string, t any, extraTags []string, ca
t, templateParseError := p.ParseTemplate(templatePath, catalog)
if templateParseError != nil {
checkOpenFileError(templateParseError)
return false, ErrCouldNotLoadTemplate(templatePath, templateParseError.Error())
return false, ErrCouldNotLoadTemplate.Msgf(templatePath, templateParseError)
}
template, ok := t.(*Template)
if !ok {
@@ -96,13 +96,13 @@ func (p *Parser) LoadTemplate(templatePath string, t any, extraTags []string, ca
validationError := validateTemplateMandatoryFields(template)
if validationError != nil {
stats.Increment(SyntaxErrorStats)
return false, ErrCouldNotLoadTemplate(templatePath, validationError.Error())
return false, ErrCouldNotLoadTemplate.Msgf(templatePath, validationError)
}
ret, err := isTemplateInfoMetadataMatch(tagFilter, template, extraTags)
if err != nil {
checkOpenFileError(err)
return ret, ErrCouldNotLoadTemplate(templatePath, err.Error())
return ret, ErrCouldNotLoadTemplate.Msgf(templatePath, err)
}
// if template loaded then check the template for optional fields to add warnings
if ret {
@@ -110,7 +110,7 @@ func (p *Parser) LoadTemplate(templatePath string, t any, extraTags []string, ca
if validationWarning != nil {
stats.Increment(SyntaxWarningStats)
checkOpenFileError(validationWarning)
return ret, ErrCouldNotLoadTemplate(templatePath, validationWarning.Error())
return ret, ErrCouldNotLoadTemplate.Msgf(templatePath, validationWarning)
}
}
return ret, nil
+8 -23
View File
@@ -1,28 +1,13 @@
package templates
import (
"fmt"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
// Helper functions for template errors with formatting
func ErrMandatoryFieldMissingFmt(field string) error {
return errkit.New(fmt.Sprintf("mandatory '%s' field is missing", field)).Build()
}
func ErrInvalidField(field, format string) error {
return errkit.New(fmt.Sprintf("invalid field format for '%s' (allowed format is %s)", field, format)).Build()
}
func ErrWarningFieldMissing(field string) error {
return errkit.New(fmt.Sprintf("field '%s' is missing", field)).Build()
}
func ErrCouldNotLoadTemplate(path, reason string) error {
return errkit.New(fmt.Sprintf("Could not load template %s: %s", path, reason)).Build()
}
func ErrLoadedWithWarnings(path, warning string) error {
return errkit.New(fmt.Sprintf("Loaded template %s: with syntax warning : %s", path, warning)).Build()
}
var (
ErrMandatoryFieldMissingFmt = errorutil.NewWithFmt("mandatory '%s' field is missing")
ErrInvalidField = errorutil.NewWithFmt("invalid field format for '%s' (allowed format is %s)")
ErrWarningFieldMissing = errorutil.NewWithFmt("field '%s' is missing")
ErrCouldNotLoadTemplate = errorutil.NewWithFmt("Could not load template %s: %s")
ErrLoadedWithWarnings = errorutil.NewWithFmt("Loaded template %s: with syntax warning : %s")
)
+2 -2
View File
@@ -41,7 +41,7 @@ func TestLoadTemplate(t *testing.T) {
name: "emptyTemplate",
template: &Template{},
isValid: false,
expectedErr: errors.New("cause=\"Could not load template emptyTemplate: cause=\\\"mandatory 'name' field is missing\\\"\\ncause=\\\"mandatory 'author' field is missing\\\"\\ncause=\\\"mandatory 'id' field is missing\\\"\""),
expectedErr: errors.New("mandatory 'name' field is missing\nmandatory 'author' field is missing\nmandatory 'id' field is missing"),
},
{
name: "emptyNameWithInvalidID",
@@ -52,7 +52,7 @@ func TestLoadTemplate(t *testing.T) {
SeverityHolder: severity.Holder{Severity: severity.Medium},
},
},
expectedErr: errors.New("cause=\"Could not load template emptyNameWithInvalidID: cause=\\\"mandatory 'name' field is missing\\\"\\ncause=\\\"invalid field format for 'id' (allowed format is ^([a-zA-Z0-9]+[-_])*[a-zA-Z0-9]+$)\\\"\""),
expectedErr: errors.New("mandatory 'name' field is missing\ninvalid field format for 'id' (allowed format is ^([a-zA-Z0-9]+[-_])*[a-zA-Z0-9]+$)"),
},
{
name: "emptySeverity",
+5 -5
View File
@@ -15,17 +15,17 @@ func validateTemplateMandatoryFields(template *Template) error {
var validateErrors []error
if utils.IsBlank(info.Name) {
validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("name"))
validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt.Msgf("name"))
}
if info.Authors.IsEmpty() {
validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("author"))
validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt.Msgf("author"))
}
if template.ID == "" {
validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("id"))
validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt.Msgf("id"))
} else if !ReTemplateID.MatchString(template.ID) {
validateErrors = append(validateErrors, ErrInvalidField("id", ReTemplateID.String()))
validateErrors = append(validateErrors, ErrInvalidField.Msgf("id", ReTemplateID.String()))
}
if len(validateErrors) > 0 {
@@ -53,7 +53,7 @@ func validateTemplateOptionalFields(template *Template) error {
var warnings []error
if template.Type() != types.WorkflowProtocol && utils.IsBlank(info.SeverityHolder.Severity.String()) {
warnings = append(warnings, ErrWarningFieldMissing("severity"))
warnings = append(warnings, ErrWarningFieldMissing.Msgf("severity"))
}
if len(warnings) > 0 {
+2 -2
View File
@@ -4,7 +4,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/keys"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
// DefaultTemplateVerifiers contains the default template verifiers
@@ -34,7 +34,7 @@ func init() {
// AddSignerToDefault adds a signer to the default list of signers
func AddSignerToDefault(s *TemplateSigner) error {
if s == nil {
return errkit.New("signer is nil").Build()
return errorutil.New("signer is nil")
}
DefaultTemplateVerifiers = append(DefaultTemplateVerifiers, s)
return nil
+3 -3
View File
@@ -16,7 +16,7 @@ import (
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
var (
@@ -82,13 +82,13 @@ func (t *TemplateSigner) Sign(data []byte, tmpl SignableTemplate) (string, error
arr := strings.SplitN(string(existingSignature), ":", 3)
if len(arr) == 2 {
// signature has no fragment
return "", errkit.New("signer: re-signing code templates are not allowed for security reasons.").Build()
return "", errorutil.NewWithTag("signer", "re-signing code templates are not allowed for security reasons.")
}
if len(arr) == 3 {
// signature has fragment verify if it is equal to current fragment
fragment := t.GetUserFragment()
if fragment != arr[2] {
return "", errkit.New("signer: re-signing code templates are not allowed for security reasons.").Build()
return "", errorutil.NewWithTag("signer", "re-signing code templates are not allowed for security reasons.")
}
}
}
+4 -4
View File
@@ -14,7 +14,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/templates/extensions"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/signer"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
)
// Due to file references in sensitive fields of template
@@ -28,7 +28,7 @@ var (
_ = protocolstate.Init(defaultOpts)
_ = protocolinit.Init(defaultOpts)
})
ErrNotATemplate = errkit.New("signer: given filePath is not a template").Build()
ErrNotATemplate = errorutil.NewWithTag("signer", "given filePath is not a template")
)
// UseOptionsForSigner sets the options to use for signing templates
@@ -68,7 +68,7 @@ func SignTemplate(templateSigner *signer.TemplateSigner, templatePath string) er
template, bin, err := getTemplate(templatePath)
if err != nil {
return errkit.Append(errkit.New("failed to get template from disk"), err)
return errorutil.NewWithErr(err).Msgf("failed to get template from disk")
}
if len(template.Workflows) > 0 {
// signing workflows is not supported at least yet
@@ -100,7 +100,7 @@ func getTemplate(templatePath string) (*Template, []byte, error) {
}
template, err := ParseTemplateFromReader(bytes.NewReader(bin), nil, executerOpts)
if err != nil {
return nil, bin, errkit.Append(errkit.New("failed to parse template"), err)
return nil, bin, errorutil.NewWithErr(err).Msgf("failed to parse template")
}
return template, bin, nil
}
+8 -9
View File
@@ -2,7 +2,6 @@
package templates
import (
"fmt"
"io"
"path/filepath"
"strconv"
@@ -25,7 +24,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/utils"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
"github.com/projectdiscovery/nuclei/v3/pkg/workflows"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
"go.uber.org/multierr"
"gopkg.in/yaml.v2"
@@ -326,14 +325,14 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error
*template = Template(*alias)
if !ReTemplateID.MatchString(template.ID) {
return errkit.New(fmt.Sprintf("invalid template: template id must match expression %v", ReTemplateID)).Build()
return errorutil.New("template id must match expression %v", ReTemplateID).WithTag("invalid template")
}
info := template.Info
if utils.IsBlank(info.Name) {
return errkit.New("invalid template: no template name field provided").Build()
return errorutil.New("no template name field provided").WithTag("invalid template")
}
if info.Authors.IsEmpty() {
return errkit.New("invalid template: no template author field provided").Build()
return errorutil.New("no template author field provided").WithTag("invalid template")
}
if len(template.RequestsHTTP) > 0 || len(template.RequestsNetwork) > 0 {
@@ -341,10 +340,10 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error
}
if len(alias.RequestsHTTP) > 0 && len(alias.RequestsWithHTTP) > 0 {
return errkit.New("invalid template: use http or requests, both are not supported").Build()
return errorutil.New("use http or requests, both are not supported").WithTag("invalid template")
}
if len(alias.RequestsNetwork) > 0 && len(alias.RequestsWithTCP) > 0 {
return errkit.New("invalid template: use tcp or network, both are not supported").Build()
return errorutil.New("use tcp or network, both are not supported").WithTag("invalid template")
}
if len(alias.RequestsWithHTTP) > 0 {
template.RequestsHTTP = alias.RequestsWithHTTP
@@ -362,7 +361,7 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error
var tempmap yaml.MapSlice
err = unmarshal(&tempmap)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to unmarshal multi protocol template %s", template.ID)), err)
return errorutil.NewWithErr(err).Msgf("failed to unmarshal multi protocol template %s", template.ID)
}
arr := []string{}
for _, v := range tempmap {
@@ -546,7 +545,7 @@ func (template *Template) UnmarshalJSON(data []byte) error {
var tempMap map[string]interface{}
err = json.Unmarshal(data, &tempMap)
if err != nil {
return errkit.Append(errkit.New(fmt.Sprintf("failed to unmarshal multi protocol template %s", template.ID)), err)
return errorutil.NewWithErr(err).Msgf("failed to unmarshal multi protocol template %s", template.ID)
}
arr := []string{}
for k := range tempMap {
+8 -8
View File
@@ -16,16 +16,16 @@ import (
"github.com/kitabisa/go-ci"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
mapsutil "github.com/projectdiscovery/utils/maps"
"go.uber.org/multierr"
)
// ErrInvalidRequestID returns an error for invalid request IDs
func ErrInvalidRequestID(templateID, requestID string) error {
return errkit.New(fmt.Sprintf("[%s] invalid request id '%s' provided", templateID, requestID)).Build()
}
var (
// ErrInvalidRequestID is a request id error
ErrInvalidRequestID = errorutil.NewWithFmt("[%s] invalid request id '%s' provided")
)
// ProtoOptions are options that can be passed to flow protocol callback
// ex: dns(protoOptions) <- protoOptions are optional and can be anything
@@ -256,12 +256,12 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error {
f.reconcileProgress()
if err != nil {
ctx.LogError(err)
return errkit.Append(errkit.New(fmt.Sprintf("failed to execute flow\n%v\n", f.options.Flow)), err)
return errorutil.NewWithErr(err).Msgf("failed to execute flow\n%v\n", f.options.Flow)
}
runtimeErr := f.GetRuntimeErrors()
if runtimeErr != nil {
ctx.LogError(runtimeErr)
return errkit.Append(errkit.New("got following errors while executing flow"), runtimeErr)
return errorutil.NewWithErr(runtimeErr).Msgf("got following errors while executing flow")
}
return nil
@@ -283,7 +283,7 @@ func (f *FlowExecutor) reconcileProgress() {
func (f *FlowExecutor) GetRuntimeErrors() error {
errs := []error{}
for proto, err := range f.allErrs.GetAll() {
errs = append(errs, errkit.Append(errkit.New(fmt.Sprintf("failed to execute %v protocol", proto)), err))
errs = append(errs, errorutil.NewWithErr(err).Msgf("failed to execute %v protocol", proto))
}
return multierr.Combine(errs...)
}
+1 -1
View File
@@ -61,7 +61,7 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma
if !ok {
f.ctx.LogError(fmt.Errorf("[%v] invalid request id '%s' provided", f.options.TemplateID, id))
// compile error
if err := f.allErrs.Set(opts.protoName+":"+id, ErrInvalidRequestID(f.options.TemplateID, id)); err != nil {
if err := f.allErrs.Set(opts.protoName+":"+id, ErrInvalidRequestID.Msgf(f.options.TemplateID, id)); err != nil {
f.ctx.LogError(fmt.Errorf("failed to store flow runtime errors got %v", err))
}
return matcherStatus.Load()
+5 -6
View File
@@ -1,7 +1,6 @@
package types
import (
"fmt"
"io"
"os"
"path/filepath"
@@ -15,7 +14,7 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
fileutil "github.com/projectdiscovery/utils/file"
folderutil "github.com/projectdiscovery/utils/folder"
unitutils "github.com/projectdiscovery/utils/unit"
@@ -831,7 +830,7 @@ func (options *Options) defaultLoadHelperFile(helperFile, templatePath string, c
}
f, err := os.Open(helperFile)
if err != nil {
return nil, errkit.Append(errkit.New(fmt.Sprintf("could not open file %v", helperFile)), err)
return nil, errorutil.NewWithErr(err).Msgf("could not open file %v", helperFile)
}
return f, nil
}
@@ -856,12 +855,12 @@ func (o *Options) GetValidAbsPath(helperFilePath, templatePath string) (string,
// CleanPath resolves using CWD and cleans the path
helperFilePath, err = fileutil.CleanPath(helperFilePath)
if err != nil {
return "", errkit.Append(errkit.New(fmt.Sprintf("could not clean helper file path %v", helperFilePath)), err)
return "", errorutil.NewWithErr(err).Msgf("could not clean helper file path %v", helperFilePath)
}
templatePath, err = fileutil.CleanPath(templatePath)
if err != nil {
return "", errkit.Append(errkit.New(fmt.Sprintf("could not clean template path %v", templatePath)), err)
return "", errorutil.NewWithErr(err).Msgf("could not clean template path %v", templatePath)
}
// As per rule 2, if template and helper file exist in same directory or helper file existed in any child dir of template dir
@@ -872,7 +871,7 @@ func (o *Options) GetValidAbsPath(helperFilePath, templatePath string) (string,
}
// all other cases are denied
return "", errkit.New(fmt.Sprintf("access to helper file %v denied", helperFilePath)).Build()
return "", errorutil.New("access to helper file %v denied", helperFilePath)
}
// SetExecutionID sets the execution ID for the options