From b14e63404710fbc28d869fbacf982e0a8b79341e Mon Sep 17 00:00:00 2001 From: Ice3man Date: Mon, 28 Apr 2025 18:56:35 +0530 Subject: [PATCH 001/135] feat: added support to mssql for execute query --- pkg/js/generated/ts/mssql.ts | 28 ++++++++++++++++++++ pkg/js/libs/mssql/mssql.go | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/pkg/js/generated/ts/mssql.ts b/pkg/js/generated/ts/mssql.ts index 947aa0e9e..632abaa2e 100755 --- a/pkg/js/generated/ts/mssql.ts +++ b/pkg/js/generated/ts/mssql.ts @@ -63,5 +63,33 @@ export class MSSQLClient { } + /** + * ExecuteQuery connects to MS SQL database using given credentials and executes a query. + * It returns the results of the query or an error if something goes wrong. + * @example + * ```javascript + * const mssql = require('nuclei/mssql'); + * const client = new mssql.MSSQLClient; + * const result = client.ExecuteQuery('acme.com', 1433, 'username', 'password', 'master', 'SELECT @@version'); + * log(to_json(result)); + * ``` + */ + public ExecuteQuery(host: string, port: number, username: string): SQLResult | null | null { + return null; + } + + +} + + + +/** + * SQLResult Interface + */ +export interface SQLResult { + + Count?: number, + + Columns?: string[], } diff --git a/pkg/js/libs/mssql/mssql.go b/pkg/js/libs/mssql/mssql.go index 5660cc2a6..6b2c408d0 100644 --- a/pkg/js/libs/mssql/mssql.go +++ b/pkg/js/libs/mssql/mssql.go @@ -11,6 +11,7 @@ import ( _ "github.com/microsoft/go-mssqldb" "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/mssql" + "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) @@ -132,3 +133,53 @@ func isMssql(host string, port int) (bool, error) { } return false, nil } + +// ExecuteQuery connects to MS SQL database using given credentials and executes a query. +// It returns the results of the query or an error if something goes wrong. +// @example +// ```javascript +// const mssql = require('nuclei/mssql'); +// const client = new mssql.MSSQLClient; +// const result = client.ExecuteQuery('acme.com', 1433, 'username', 'password', 'master', 'SELECT @@version'); +// log(to_json(result)); +// ``` +func (c *MSSQLClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) { + if host == "" || port <= 0 { + return nil, fmt.Errorf("invalid host or port") + } + if !protocolstate.IsHostAllowed(host) { + // host is not valid according to network policy + return nil, protocolstate.ErrHostDenied.Msgf(host) + } + + target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + + connString := fmt.Sprintf("sqlserver://%s:%s@%s?database=%s&connection+timeout=30", + url.PathEscape(username), + url.PathEscape(password), + target, + dbName) + + db, err := sql.Open("sqlserver", connString) + if err != nil { + return nil, err + } + defer db.Close() + + db.SetMaxOpenConns(1) + db.SetMaxIdleConns(0) + + rows, err := db.Query(query) + if err != nil { + return nil, err + } + + data, err := utils.UnmarshalSQLRows(rows) + if err != nil { + if data != nil && len(data.Rows) > 0 { + return data, nil + } + return nil, err + } + return data, nil +} From 088425d3510eec19aaf0a6414e418ce904703932 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 1 May 2025 22:44:29 +0200 Subject: [PATCH 002/135] adding mssql check --- pkg/js/libs/mssql/mssql.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/js/libs/mssql/mssql.go b/pkg/js/libs/mssql/mssql.go index 6b2c408d0..938318a85 100644 --- a/pkg/js/libs/mssql/mssql.go +++ b/pkg/js/libs/mssql/mssql.go @@ -154,6 +154,14 @@ func (c *MSSQLClient) ExecuteQuery(host string, port int, username, password, db target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) + ok, err := c.IsMssql(host, port) + if err != nil { + return nil, err + } + if !ok { + return nil, fmt.Errorf("not a mssql service") + } + connString := fmt.Sprintf("sqlserver://%s:%s@%s?database=%s&connection+timeout=30", url.PathEscape(username), url.PathEscape(password), From a7a009084c0dc0b74772a1f3bee56829af6a8205 Mon Sep 17 00:00:00 2001 From: 23kbps <86248851+23kbps@users.noreply.github.com> Date: Sat, 3 May 2025 15:28:18 +0700 Subject: [PATCH 003/135] Fix ingress template in helm chart --- helm/templates/interactsh-ingress.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/helm/templates/interactsh-ingress.yaml b/helm/templates/interactsh-ingress.yaml index 9c80eb4fe..58cc3701d 100644 --- a/helm/templates/interactsh-ingress.yaml +++ b/helm/templates/interactsh-ingress.yaml @@ -1,6 +1,7 @@ {{- if .Values.interactsh.ingress.enabled -}} {{- $fullName := include "nuclei.fullname" . -}} -{{- $svcPort := .Values.service.port -}} +{{- $svcPort := .Values.interactsh.service.port -}} +{{- $svcName := .Values.interactsh.service.name -}} {{- if and .Values.interactsh.ingress.className (not (semverCompare ">=1.20-0" .Capabilities.KubeVersion.GitVersion)) }} {{- if not (hasKey .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class") }} {{- $_ := set .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class" .Values.interactsh.ingress.className}} @@ -49,11 +50,11 @@ spec: backend: {{- if semverCompare ">=1.20-0" $.Capabilities.KubeVersion.GitVersion }} service: - name: {{ $fullName }} + name: {{ $svcName }} port: number: {{ $svcPort }} {{- else }} - serviceName: {{ $fullName }} + serviceName: {{ $svcName }} servicePort: {{ $svcPort }} {{- end }} {{- end }} From 4801cc65ef40a681eaa81f14ebba9a9952191c81 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Wed, 7 May 2025 17:22:15 +0530 Subject: [PATCH 004/135] feat: fixed max-host-error blocking + progress mismatch + misc (#6193) * feat: fixed max-host-error blocking wrong port for template with error * feat: log total results with time taken at end of execution * bugfix: skip non-executed requests with progress in flow protocol * feat: fixed request calculation in http protocol for progress * misc adjustments --------- Co-authored-by: Ice3man --- internal/runner/runner.go | 27 +++++++- pkg/core/execute_options.go | 2 + pkg/output/multi_writer.go | 10 +++ pkg/output/output.go | 9 +++ pkg/output/output_stats.go | 3 + pkg/progress/progress.go | 4 +- .../common/hosterrorscache/hosterrorscache.go | 18 ++++-- pkg/protocols/http/build_request.go | 8 --- pkg/protocols/http/http.go | 21 +----- pkg/protocols/http/request.go | 14 ++-- pkg/protocols/http/request_generator.go | 64 +++++++++++++++++++ pkg/testutils/testutils.go | 4 ++ pkg/tmplexec/flow/flow_executor.go | 16 +++++ pkg/tmplexec/flow/flow_internal.go | 9 +++ 14 files changed, 168 insertions(+), 41 deletions(-) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 85fe0ea75..424d27116 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -702,6 +702,7 @@ func (r *Runner) RunEnumeration() error { }() } + now := time.Now() enumeration := false var results *atomic.Bool results, err = r.runStandardEnumeration(executorOpts, store, executorEngine) @@ -725,11 +726,17 @@ func (r *Runner) RunEnumeration() error { } r.fuzzFrequencyCache.Close() + r.progress.Stop() + timeTaken := time.Since(now) // todo: error propagation without canonical straight error check is required by cloud? // use safe dereferencing to avoid potential panics in case of previous unchecked errors if v := ptrutil.Safe(results); !v.Load() { - gologger.Info().Msgf("No results found. Better luck next time!") + gologger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken)) + } else { + matchCount := r.output.ResultCount() + gologger.Info().Msgf("Scan completed in %s. %d matches found.", shortDur(timeTaken), matchCount) } + // check if a passive scan was requested but no target was provided if r.options.OfflineHTTP && len(r.options.Targets) == 0 && r.options.TargetsFilePath == "" { return errors.Wrap(err, "missing required input (http response) to run passive templates") @@ -738,6 +745,24 @@ func (r *Runner) RunEnumeration() error { return err } +func shortDur(d time.Duration) string { + if d < time.Minute { + return d.String() + } + + // Truncate to the nearest minute + d = d.Truncate(time.Minute) + s := d.String() + + if strings.HasSuffix(s, "m0s") { + s = s[:len(s)-2] + } + if strings.HasSuffix(s, "h0m") { + s = s[:len(s)-2] + } + return s +} + func (r *Runner) isInputNonHTTP() bool { var nonURLInput bool r.inputProvider.Iterate(func(value *contextargs.MetaInput) bool { diff --git a/pkg/core/execute_options.go b/pkg/core/execute_options.go index aa47bc44f..fae26b456 100644 --- a/pkg/core/execute_options.go +++ b/pkg/core/execute_options.go @@ -110,6 +110,8 @@ func (e *Engine) executeTemplateSpray(ctx context.Context, templatesList []*temp defer wp.Wait() for _, template := range templatesList { + template := template + select { case <-ctx.Done(): return results diff --git a/pkg/output/multi_writer.go b/pkg/output/multi_writer.go index 8ea729b4b..17b1c725a 100644 --- a/pkg/output/multi_writer.go +++ b/pkg/output/multi_writer.go @@ -65,3 +65,13 @@ func (mw *MultiWriter) RequestStatsLog(statusCode, response string) { writer.RequestStatsLog(statusCode, response) } } + +func (mw *MultiWriter) ResultCount() int { + count := 0 + for _, writer := range mw.writers { + if count := writer.ResultCount(); count > 0 { + return count + } + } + return count +} diff --git a/pkg/output/output.go b/pkg/output/output.go index 5c84bed30..e85774b83 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -54,6 +54,8 @@ type Writer interface { RequestStatsLog(statusCode, response string) // WriteStoreDebugData writes the request/response debug data to file WriteStoreDebugData(host, templateID, eventType string, data string) + // ResultCount returns the total number of results written + ResultCount() int } // StandardWriter is a writer writing output to file and screen for results. @@ -79,6 +81,8 @@ type StandardWriter struct { // JSONLogRequestHook is a hook that can be used to log request/response // when using custom server code with output JSONLogRequestHook func(*JSONLogRequest) + + resultCount atomic.Int32 } var _ Writer = &StandardWriter{} @@ -287,6 +291,10 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) { return writer, nil } +func (w *StandardWriter) ResultCount() int { + return int(w.resultCount.Load()) +} + // Write writes the event to file and/or screen. func (w *StandardWriter) Write(event *ResultEvent) error { // Enrich the result event with extra metadata on the template-path and url. @@ -336,6 +344,7 @@ func (w *StandardWriter) Write(event *ResultEvent) error { _, _ = w.outputFile.Write([]byte("\n")) } } + w.resultCount.Add(1) return nil } diff --git a/pkg/output/output_stats.go b/pkg/output/output_stats.go index 7b0d509cd..68a234d85 100644 --- a/pkg/output/output_stats.go +++ b/pkg/output/output_stats.go @@ -49,3 +49,6 @@ func (tw *StatsOutputWriter) RequestStatsLog(statusCode, response string) { tw.Tracker.TrackStatusCode(statusCode) tw.Tracker.TrackWAFDetected(response) } +func (tw *StatsOutputWriter) ResultCount() int { + return 0 +} diff --git a/pkg/progress/progress.go b/pkg/progress/progress.go index 1ffb22cee..853fb103d 100644 --- a/pkg/progress/progress.go +++ b/pkg/progress/progress.go @@ -120,9 +120,7 @@ func (p *StatsTicker) IncrementRequests() { // SetRequests sets the counter by incrementing it with a delta func (p *StatsTicker) SetRequests(count uint64) { - value, _ := p.stats.GetCounter("requests") - delta := count - value - p.stats.IncrementCounter("requests", int(delta)) + p.stats.IncrementCounter("requests", int(count)) } // IncrementMatched increments the matched counter by 1. diff --git a/pkg/protocols/common/hosterrorscache/hosterrorscache.go b/pkg/protocols/common/hosterrorscache/hosterrorscache.go index 3943eef7e..3039dbdf0 100644 --- a/pkg/protocols/common/hosterrorscache/hosterrorscache.go +++ b/pkg/protocols/common/hosterrorscache/hosterrorscache.go @@ -89,6 +89,9 @@ func (c *Cache) NormalizeCacheValue(value string) string { u, err := url.ParseRequestURI(value) if err != nil || u.Host == "" { + if strings.Contains(value, ":") { + return normalizedValue + } u, err2 := url.ParseRequestURI("https://" + value) if err2 != nil { return normalizedValue @@ -236,14 +239,19 @@ func (c *Cache) GetKeyFromContext(ctx *contextargs.Context, err error) string { // should be reflected in contextargs but it is not yet reflected in some cases // and needs refactor of ScanContext + ContextArgs to achieve that // i.e why we use real address from error if present - address := ctx.MetaInput.Address() - // get address override from error + var address string + + // 1. the address carried inside the error (if the transport sets it) if err != nil { - tmp := errkit.GetAttrValue(err, "address") - if tmp.Any() != nil { - address = tmp.String() + if v := errkit.GetAttrValue(err, "address"); v.Any() != nil { + address = v.String() } } + + if address == "" { + address = ctx.MetaInput.Address() + } + finalValue := c.NormalizeCacheValue(address) return finalValue } diff --git a/pkg/protocols/http/build_request.go b/pkg/protocols/http/build_request.go index 3cde12d88..1cb9553c9 100644 --- a/pkg/protocols/http/build_request.go +++ b/pkg/protocols/http/build_request.go @@ -123,14 +123,6 @@ func (g *generatedRequest) URL() string { return "" } -// Total returns the total number of requests for the generator -func (r *requestGenerator) Total() int { - if r.payloadIterator != nil { - return len(r.request.Raw) * r.payloadIterator.Remaining() - } - return len(r.request.Path) -} - // Make creates a http request for the provided input. // It returns ErrNoMoreRequests as error when all the requests have been exhausted. func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context, reqData string, payloads, dynamicValues map[string]interface{}) (gr *generatedRequest, err error) { diff --git a/pkg/protocols/http/http.go b/pkg/protocols/http/http.go index 78710f79c..0b30a7408 100644 --- a/pkg/protocols/http/http.go +++ b/pkg/protocols/http/http.go @@ -501,7 +501,6 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { request.Threads = options.GetThreadsForNPayloadRequests(request.Requests(), request.Threads) } } - return nil } @@ -517,24 +516,8 @@ func (request *Request) RebuildGenerator() error { // Requests returns the total number of requests the YAML rule will perform func (request *Request) Requests() int { - if request.generator != nil { - payloadRequests := request.generator.NewIterator().Total() - if len(request.Raw) > 0 { - payloadRequests = payloadRequests * len(request.Raw) - } - if len(request.Path) > 0 { - payloadRequests = payloadRequests * len(request.Path) - } - return payloadRequests - } - if len(request.Raw) > 0 { - requests := len(request.Raw) - if requests == 1 && request.RaceNumberRequests != 0 { - requests *= request.RaceNumberRequests - } - return requests - } - return len(request.Path) + generator := request.newGenerator(false) + return generator.Total() } const ( diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index 2cc32f5bf..6d8ad3e1d 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -41,7 +41,6 @@ import ( "github.com/projectdiscovery/rawhttp" convUtil "github.com/projectdiscovery/utils/conversion" "github.com/projectdiscovery/utils/errkit" - errorutil "github.com/projectdiscovery/utils/errors" httpUtils "github.com/projectdiscovery/utils/http" "github.com/projectdiscovery/utils/reader" sliceutil "github.com/projectdiscovery/utils/slice" @@ -484,7 +483,6 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa if err == types.ErrNoMoreRequests { return true, nil } - request.options.Progress.IncrementFailedRequestsBy(int64(generator.Total())) return true, err } // ideally if http template used a custom port or hostname @@ -541,14 +539,19 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa if errors.Is(execReqErr, ErrMissingVars) { return true, nil } + if execReqErr != nil { + request.markHostError(updatedInput, execReqErr) + // if applicable mark the host as unresponsive - requestErr = errorutil.NewWithErr(execReqErr).Msgf("got err while executing %v", generatedHttpRequest.URL()) + reqKitErr := errkit.FromError(execReqErr) + reqKitErr.Msgf("got err while executing %v", generatedHttpRequest.URL()) + + requestErr = reqKitErr request.options.Progress.IncrementFailedRequestsBy(1) } else { request.options.Progress.IncrementRequests() } - request.markHostError(updatedInput, execReqErr) // If this was a match, and we want to stop at first match, skip all further requests. shouldStopAtFirstMatch := generatedHttpRequest.original.options.Options.StopAtFirstMatch || generatedHttpRequest.original.options.StopAtFirstMatch || request.StopAtFirstMatch @@ -585,6 +588,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa requestErr = gotErr } if skip || gotErr != nil { + request.options.Progress.SetRequests(uint64(generator.Remaining() + 1)) break } } @@ -1212,7 +1216,7 @@ func (request *Request) newContext(input *contextargs.Context) context.Context { // markHostError checks if the error is a unreponsive host error and marks it func (request *Request) markHostError(input *contextargs.Context, err error) { - if request.options.HostErrorsCache != nil { + if request.options.HostErrorsCache != nil && err != nil { request.options.HostErrorsCache.MarkFailedOrRemove(request.options.ProtocolType.String(), input, err) } } diff --git a/pkg/protocols/http/request_generator.go b/pkg/protocols/http/request_generator.go index b15df1be9..4c4c701a8 100644 --- a/pkg/protocols/http/request_generator.go +++ b/pkg/protocols/http/request_generator.go @@ -135,3 +135,67 @@ func (r *requestGenerator) hasMarker(request string, mark flowMark) bool { fo, hasOverrides := parseFlowAnnotations(request) return hasOverrides && fo == mark } + +// Remaining returns the number of requests that are still left to be +// generated (and therefore to be sent) by this generator. +func (r *requestGenerator) Remaining() int { + var sequence []string + switch { + case len(r.request.Path) > 0: + sequence = r.request.Path + case len(r.request.Raw) > 0: + sequence = r.request.Raw + default: + return 0 + } + + remainingInCurrentPass := 0 + for i := r.currentIndex; i < len(sequence); i++ { + if !r.hasMarker(sequence[i], Once) { + remainingInCurrentPass++ + } + } + + if r.payloadIterator == nil { + return remainingInCurrentPass + } + + numRemainingPayloadSets := r.payloadIterator.Remaining() + totalValidInSequence := 0 + for _, req := range sequence { + if !r.hasMarker(req, Once) { + totalValidInSequence++ + } + } + + // Total remaining = remaining in current pass + (remaining payload sets * requests per full pass) + return remainingInCurrentPass + numRemainingPayloadSets*totalValidInSequence +} + +func (r *requestGenerator) Total() int { + var sequence []string + switch { + case len(r.request.Path) > 0: + sequence = r.request.Path + case len(r.request.Raw) > 0: + sequence = r.request.Raw + default: + return 0 + } + + applicableRequests := 0 + additionalRequests := 0 + for _, request := range sequence { + if !r.hasMarker(request, Once) { + applicableRequests++ + } else { + additionalRequests++ + } + } + + if r.payloadIterator == nil { + return applicableRequests + additionalRequests + } + + return (applicableRequests * r.payloadIterator.Total()) + additionalRequests +} diff --git a/pkg/testutils/testutils.go b/pkg/testutils/testutils.go index d59af2f7b..5f791c2c1 100644 --- a/pkg/testutils/testutils.go +++ b/pkg/testutils/testutils.go @@ -133,6 +133,10 @@ func (m *MockOutputWriter) Colorizer() aurora.Aurora { return m.aurora } +func (m *MockOutputWriter) ResultCount() int { + return 0 +} + // Write writes the event to file and/or screen. func (m *MockOutputWriter) Write(result *output.ResultEvent) error { if m.WriteCallback != nil { diff --git a/pkg/tmplexec/flow/flow_executor.go b/pkg/tmplexec/flow/flow_executor.go index 6e71cf840..62112e0f8 100644 --- a/pkg/tmplexec/flow/flow_executor.go +++ b/pkg/tmplexec/flow/flow_executor.go @@ -51,6 +51,8 @@ type FlowExecutor struct { // these are keys whose values are meant to be flatten before executing // a request ex: if dynamic extractor returns ["value"] it will be converted to "value" flattenKeys []string + + executed *mapsutil.SyncLockMap[string, struct{}] } // NewFlowExecutor creates a new flow executor from a list of requests @@ -98,6 +100,7 @@ func NewFlowExecutor(requests []protocols.Request, ctx *scan.ScanContext, option results: results, ctx: ctx, program: program, + executed: mapsutil.NewSyncLockMap[string, struct{}](), } return f, nil } @@ -243,6 +246,7 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error { // pass flow and execute the js vm and handle errors _, err := runtime.RunProgram(f.program) + f.reconcileProgress() if err != nil { ctx.LogError(err) return errorutil.NewWithErr(err).Msgf("failed to execute flow\n%v\n", f.options.Flow) @@ -256,6 +260,18 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error { return nil } +func (f *FlowExecutor) reconcileProgress() { + for proto, list := range f.allProtocols { + for idx, req := range list { + key := requestKey(proto, req, strconv.Itoa(idx+1)) + if _, seen := f.executed.Get(key); !seen { + // never executed → pretend it finished so that stats match + f.options.Progress.SetRequests(uint64(req.Requests())) + } + } + } +} + // GetRuntimeErrors returns all runtime errors (i.e errors from all protocol combined) func (f *FlowExecutor) GetRuntimeErrors() error { errs := []error{} diff --git a/pkg/tmplexec/flow/flow_internal.go b/pkg/tmplexec/flow/flow_internal.go index 92a852f9d..03cc29596 100644 --- a/pkg/tmplexec/flow/flow_internal.go +++ b/pkg/tmplexec/flow/flow_internal.go @@ -75,6 +75,8 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma } } err := req.ExecuteWithResults(inputItem, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), output.InternalEvent{}, f.protocolResultCallback(req, matcherStatus, opts)) + // Mark the request as seen + _ = f.executed.Set(requestKey(opts.protoName, req, id), struct{}{}) if err != nil { index := id err = f.allErrs.Set(opts.protoName+":"+index, err) @@ -86,6 +88,13 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma return matcherStatus.Load() } +func requestKey(proto string, req protocols.Request, id string) string { + if id == "" { + id = req.GetID() + } + return proto + ":" + id +} + // protocolResultCallback returns a callback that is executed // after execution of each protocol request func (f *FlowExecutor) protocolResultCallback(req protocols.Request, matcherStatus *atomic.Bool, _ *ProtoOptions) func(result *output.InternalWrappedEvent) { From 3bb44d588f7c3ca27d81bf117a0ee1363c8d8f0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 18:04:33 +0530 Subject: [PATCH 005/135] chore(deps): bump the modules group with 4 updates (#6207) Bumps the modules group with 4 updates: [github.com/projectdiscovery/retryablehttp-go](https://github.com/projectdiscovery/retryablehttp-go), [github.com/projectdiscovery/gologger](https://github.com/projectdiscovery/gologger), [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.110 to 1.0.111 - [Release notes](https://github.com/projectdiscovery/retryablehttp-go/releases) - [Commits](https://github.com/projectdiscovery/retryablehttp-go/compare/v1.0.110...v1.0.111) Updates `github.com/projectdiscovery/gologger` from 1.1.53 to 1.1.54 - [Release notes](https://github.com/projectdiscovery/gologger/releases) - [Commits](https://github.com/projectdiscovery/gologger/compare/v1.1.53...v1.1.54) Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.25 to 0.2.27 - [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases) - [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.25...v0.2.27) Updates `github.com/projectdiscovery/cdncheck` from 1.1.15 to 1.1.17 - [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.17) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/retryablehttp-go dependency-version: 1.0.111 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/gologger dependency-version: 1.1.54 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/wappalyzergo dependency-version: 0.2.27 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/cdncheck dependency-version: 1.1.17 dependency-type: indirect update-type: version-update:semver-patch dependency-group: modules ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 11 ++++------- go.sum | 30 ++++++++---------------------- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index 7f5efa7f5..820548938 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/projectdiscovery/interactsh v1.2.4 github.com/projectdiscovery/rawhttp v0.1.90 github.com/projectdiscovery/retryabledns v1.0.99 - github.com/projectdiscovery/retryablehttp-go v1.0.110 + github.com/projectdiscovery/retryablehttp-go v1.0.111 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.0 @@ -90,7 +90,7 @@ require ( github.com/projectdiscovery/fasttemplate v0.0.2 github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb github.com/projectdiscovery/goflags v0.1.74 - github.com/projectdiscovery/gologger v1.1.53 + github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/gostruct v0.0.2 github.com/projectdiscovery/gozero v0.0.3 github.com/projectdiscovery/httpx v1.7.0 @@ -103,7 +103,7 @@ require ( github.com/projectdiscovery/uncover v1.0.10 github.com/projectdiscovery/useragent v0.0.100 github.com/projectdiscovery/utils v0.4.18 - github.com/projectdiscovery/wappalyzergo v0.2.25 + github.com/projectdiscovery/wappalyzergo v0.2.27 github.com/redis/go-redis/v9 v9.1.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -202,7 +202,6 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mackerelio/go-osstat v0.2.4 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mholt/archiver/v3 v3.5.1 // indirect github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -221,7 +220,7 @@ require ( github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.15 // indirect + github.com/projectdiscovery/cdncheck v1.1.17 // indirect 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 @@ -363,10 +362,8 @@ require ( github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/nwaples/rardecode v1.1.3 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 42493e717..64946396f 100644 --- a/go.sum +++ b/go.sum @@ -116,7 +116,6 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3Uu github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs= github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= -github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= @@ -319,7 +318,6 @@ github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562 h1:ObbB2tzHWWAxzsG5futqeq2Ual2zYlo/+eMkSc5sn8w= github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562/go.mod h1:X2TOTJ+Uamd454RFp7ig2tmP3hQg0Z2Qk8gbVQmU0mk= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= @@ -485,7 +483,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -665,7 +662,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kitabisa/go-ci v1.0.3 h1:JmIUIvcercRQc/9x/v02ydCCqU4MadSHaNaOF8T2pGA= github.com/kitabisa/go-ci v1.0.3/go.mod h1:e3wBSzaJbcifXrr/Gw2ZBLn44MmeqP5WySwXyHlCK/U= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= @@ -673,7 +669,6 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= @@ -740,8 +735,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= -github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/mholt/archives v0.1.0 h1:FacgJyrjiuyomTuNA92X5GyRBRZjE43Y/lrzKIlF35Q= github.com/mholt/archives v0.1.0/go.mod h1:j/Ire/jm42GN7h90F5kzj6hf6ZFzEH66de+hmjEKu+I= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= @@ -795,9 +788,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= -github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode/v2 v2.0.1 h1:3MN6/R+Y4c7e+21U3yhWuUcf72sYmcmr6jtiuAVSH1A= github.com/nwaples/rardecode/v2 v2.0.1/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= @@ -842,7 +832,6 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -865,8 +854,8 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.15 h1:rRs3LW2MP7V8QeONVRYce6RhDcWp83O+AWmt+QQ4mBM= -github.com/projectdiscovery/cdncheck v1.1.15/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.17 h1:YSqKk05+UGSxmPIp7tlCvRegF63FUqO+mA2Wl/Je3gA= +github.com/projectdiscovery/cdncheck v1.1.17/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= github.com/projectdiscovery/dsl v0.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI= @@ -881,8 +870,8 @@ github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG90 github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY= github.com/projectdiscovery/goflags v0.1.74 h1:n85uTRj5qMosm0PFBfsvOL24I7TdWRcWq/1GynhXS7c= github.com/projectdiscovery/goflags v0.1.74/go.mod h1:UMc9/7dFz2oln+10tv6cy+7WZKTHf9UGhaNkF95emh4= -github.com/projectdiscovery/gologger v1.1.53 h1:Er5nty/kifUDSr9MLgi8pzr0bveC+jco76Ittlg/AlM= -github.com/projectdiscovery/gologger v1.1.53/go.mod h1:PLaWBQIjfIaSAfAVAJ3MZctIyStGcI3CpaN7NLIejo8= +github.com/projectdiscovery/gologger v1.1.54 h1:WMzvJ8j/4gGfPKpCttSTaYCVDU1MWQSJnk3wU8/U6Ws= +github.com/projectdiscovery/gologger v1.1.54/go.mod h1:vza/8pe2OKOt+ujFWncngknad1XWr8EnLKlbcejOyUE= github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M= github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE= github.com/projectdiscovery/gozero v0.0.3 h1:tsYkrSvWw4WdIUJyisd4MB1vRiw1X57TuVVk3p8Z3G8= @@ -911,8 +900,8 @@ github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gB github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg= github.com/projectdiscovery/retryabledns v1.0.99 h1:DJ6TewgkwqJozDOPXhoOy/cdtuzJzbIQ/BFfWNYzHpw= github.com/projectdiscovery/retryabledns v1.0.99/go.mod h1:pkPYuqtxhX6z1pYL+O6s4Lg7ubINt2jg12gsaW9O3kY= -github.com/projectdiscovery/retryablehttp-go v1.0.110 h1:qO3rkuoG4/N9KlxmfnpmdCAU2JDTq6EQzwUzvVaER/o= -github.com/projectdiscovery/retryablehttp-go v1.0.110/go.mod h1:kM6zKIqV0uRly7aTImm+3v7avRR3L2zrmgAEMNfxlbo= +github.com/projectdiscovery/retryablehttp-go v1.0.111 h1:HzkVN0IyC0RfVylBlgNoqaQgVvuUEvbDEVbpGyD/Y9M= +github.com/projectdiscovery/retryablehttp-go v1.0.111/go.mod h1:Tl6noELU9RpjwywMDw722HB038QXohl90g2ZtKSqbCI= 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= @@ -925,8 +914,8 @@ github.com/projectdiscovery/useragent v0.0.100 h1:gDZSgPQCP8D0XUny41Ch4urP+FK5Oc github.com/projectdiscovery/useragent v0.0.100/go.mod h1:8je9oUPzT5R+gjKQNEFurDSvX7fCnqW2iDGYdKMH6hY= github.com/projectdiscovery/utils v0.4.18 h1:cSjMOLXI5gAajfA6KV+0iQG4dGx2IHWLQyND/Snvw7k= github.com/projectdiscovery/utils v0.4.18/go.mod h1:y5gnpQn802iEWqf0djTRNskJlS62P5eqe1VS1+ah0tk= -github.com/projectdiscovery/wappalyzergo v0.2.25 h1:K56XmuMrEBowlu2WqSFJDkUju8DBACRKDJ8JUQrqpDk= -github.com/projectdiscovery/wappalyzergo v0.2.25/go.mod h1:F8X79ljvmvrG+EIxdxWS9VbdkVTsQupHYz+kXlp8O0o= +github.com/projectdiscovery/wappalyzergo v0.2.27 h1:u5z/3YohzwtX3n4EGDGy4XOKAXZx4JorNzZlw9CzOK0= +github.com/projectdiscovery/wappalyzergo v0.2.27/go.mod h1:F8X79ljvmvrG+EIxdxWS9VbdkVTsQupHYz+kXlp8O0o= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1094,7 +1083,6 @@ github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -1130,8 +1118,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= From 6d25a5c8cab2ae5c9c2b55d7caa6bb124c0e1347 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Thu, 8 May 2025 19:02:47 +0530 Subject: [PATCH 006/135] version update --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index be40a5de2..3b4976586 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.2` + Version = `v3.4.3` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From 36a3dab2646c98599ba839f7fe0ced318b7e22ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 05:10:38 +0000 Subject: [PATCH 007/135] chore(deps): bump the modules group with 3 updates Bumps the modules group with 3 updates: [github.com/projectdiscovery/utils](https://github.com/projectdiscovery/utils), [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) and [github.com/projectdiscovery/networkpolicy](https://github.com/projectdiscovery/networkpolicy). Updates `github.com/projectdiscovery/utils` from 0.4.18 to 0.4.19 - [Release notes](https://github.com/projectdiscovery/utils/releases) - [Changelog](https://github.com/projectdiscovery/utils/blob/main/CHANGELOG.md) - [Commits](https://github.com/projectdiscovery/utils/compare/v0.4.18...v0.4.19) Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.27 to 0.2.28 - [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases) - [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.27...v0.2.28) Updates `github.com/projectdiscovery/networkpolicy` from 0.1.13 to 0.1.14 - [Release notes](https://github.com/projectdiscovery/networkpolicy/releases) - [Commits](https://github.com/projectdiscovery/networkpolicy/compare/v0.1.13...v0.1.14) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/utils dependency-version: 0.4.19 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/wappalyzergo dependency-version: 0.2.28 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/networkpolicy dependency-version: 0.1.14 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 820548938..7ed4bc989 100644 --- a/go.mod +++ b/go.mod @@ -102,8 +102,8 @@ require ( github.com/projectdiscovery/tlsx v1.1.9 github.com/projectdiscovery/uncover v1.0.10 github.com/projectdiscovery/useragent v0.0.100 - github.com/projectdiscovery/utils v0.4.18 - github.com/projectdiscovery/wappalyzergo v0.2.27 + github.com/projectdiscovery/utils v0.4.19 + github.com/projectdiscovery/wappalyzergo v0.2.28 github.com/redis/go-redis/v9 v9.1.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -310,7 +310,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/networkpolicy v0.1.13 + github.com/projectdiscovery/networkpolicy v0.1.14 github.com/rivo/uniseg v0.4.7 // indirect github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect diff --git a/go.sum b/go.sum index 64946396f..964bb991d 100644 --- a/go.sum +++ b/go.sum @@ -890,8 +890,8 @@ 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.13 h1:1QBMYdPlMCt71PUAZAQsZgJfEXIYiJa8sgJswLUBpb4= -github.com/projectdiscovery/networkpolicy v0.1.13/go.mod h1:pat2rE4G7kbow8CQ/yOym0bdLPq8rj7ZZWn3/3OT4Rs= +github.com/projectdiscovery/networkpolicy v0.1.14 h1:XnwpGjF+h9xgwEIgrFG3G+7cGRPwh6FkxgQaLuw4rv4= +github.com/projectdiscovery/networkpolicy v0.1.14/go.mod h1:pat2rE4G7kbow8CQ/yOym0bdLPq8rj7ZZWn3/3OT4Rs= github.com/projectdiscovery/ratelimit v0.0.80 h1:kDZ9Rgd/EiDR3fw8Ugtp4xVMaMZNzlEO8zCD4QholaE= github.com/projectdiscovery/ratelimit v0.0.80/go.mod h1:UW6g3VZbX+wI6WLXsexWGpSYnaQ79Uv+VewRj2+pzXQ= github.com/projectdiscovery/rawhttp v0.1.90 h1:LOSZ6PUH08tnKmWsIwvwv1Z/4zkiYKYOSZ6n+8RFKtw= @@ -912,10 +912,10 @@ github.com/projectdiscovery/uncover v1.0.10 h1:FdnBYgynGUtjIsW5WPIIhadR1Smcghik9 github.com/projectdiscovery/uncover v1.0.10/go.mod h1:l7QQ+mBc7bLK4tqYqPyo9nrYdz1K8vaGZWKYihkHmAs= github.com/projectdiscovery/useragent v0.0.100 h1:gDZSgPQCP8D0XUny41Ch4urP+FK5OcM5TB1btwCg4Gk= github.com/projectdiscovery/useragent v0.0.100/go.mod h1:8je9oUPzT5R+gjKQNEFurDSvX7fCnqW2iDGYdKMH6hY= -github.com/projectdiscovery/utils v0.4.18 h1:cSjMOLXI5gAajfA6KV+0iQG4dGx2IHWLQyND/Snvw7k= -github.com/projectdiscovery/utils v0.4.18/go.mod h1:y5gnpQn802iEWqf0djTRNskJlS62P5eqe1VS1+ah0tk= -github.com/projectdiscovery/wappalyzergo v0.2.27 h1:u5z/3YohzwtX3n4EGDGy4XOKAXZx4JorNzZlw9CzOK0= -github.com/projectdiscovery/wappalyzergo v0.2.27/go.mod h1:F8X79ljvmvrG+EIxdxWS9VbdkVTsQupHYz+kXlp8O0o= +github.com/projectdiscovery/utils v0.4.19 h1:rWOOTWUMQK9gvgH01rrw0qFi0hrh712hM1pCUzapCqA= +github.com/projectdiscovery/utils v0.4.19/go.mod h1:y5gnpQn802iEWqf0djTRNskJlS62P5eqe1VS1+ah0tk= +github.com/projectdiscovery/wappalyzergo v0.2.28 h1:fd4xne6ndxJFSqJfSDAXmR3G87SZQdOYFTapHk4Ksh4= +github.com/projectdiscovery/wappalyzergo v0.2.28/go.mod h1:F8X79ljvmvrG+EIxdxWS9VbdkVTsQupHYz+kXlp8O0o= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= From bc551fc3f1273103e1eec6a25ef7085378f72a6e Mon Sep 17 00:00:00 2001 From: Chris Grieger Date: Wed, 14 May 2025 16:13:44 +0200 Subject: [PATCH 008/135] fix: improve headless engine startup and shutdown Fixes #6221 Instead of enumerating all chrome processes to determine which ones need to be killed on shutdown, use the launcher.Kill() method to terminate the process that was launched for this browser instance. --- pkg/protocols/headless/engine/engine.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pkg/protocols/headless/engine/engine.go b/pkg/protocols/headless/engine/engine.go index 20942c261..0a83eef98 100644 --- a/pkg/protocols/headless/engine/engine.go +++ b/pkg/protocols/headless/engine/engine.go @@ -15,16 +15,15 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" fileutil "github.com/projectdiscovery/utils/file" osutils "github.com/projectdiscovery/utils/os" - processutil "github.com/projectdiscovery/utils/process" ) // Browser is a browser structure for nuclei headless module type Browser struct { - customAgent string - tempDir string - previousPIDs map[int32]struct{} // track already running PIDs - engine *rod.Browser - options *types.Options + customAgent string + tempDir string + engine *rod.Browser + options *types.Options + launcher *launcher.Launcher // use getHTTPClient to get the http client httpClient *http.Client httpClientOnce *sync.Once @@ -36,7 +35,6 @@ func New(options *types.Options) (*Browser, error) { if err != nil { return nil, errors.Wrap(err, "could not create temporary directory") } - previousPIDs := processutil.FindProcesses(processutil.IsChromeProcess) chromeLauncher := launcher.New(). Leakless(false). @@ -110,8 +108,8 @@ func New(options *types.Options) (*Browser, error) { engine: browser, options: options, httpClientOnce: &sync.Once{}, + launcher: chromeLauncher, } - engine.previousPIDs = previousPIDs return engine, nil } @@ -143,6 +141,6 @@ func (b *Browser) getHTTPClient() (*http.Client, error) { // Close closes the browser engine func (b *Browser) Close() { b.engine.Close() + b.launcher.Kill() os.RemoveAll(b.tempDir) - processutil.CloseProcesses(processutil.IsChromeProcess, b.previousPIDs) } From 44e58f1d3b088433d1014f71921896a2dabeebbc Mon Sep 17 00:00:00 2001 From: proabiral <22173232+proabiral@users.noreply.github.com> Date: Thu, 15 May 2025 15:58:11 +0545 Subject: [PATCH 009/135] Update README.md with new required go version (#6223) latest version of nuclei requires 1.23. 2.023 go: github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest: github.com/projectdiscovery/nuclei/v3@v3.4.3 requires go >= 1.23.0 (running go 1.22.2; GOTOOLCHAIN=local) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa76e3695..1153b8e1c 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ Browse the full Nuclei [**`documentation here`**](https://docs.projectdiscovery. ### Installation -`nuclei` requires **go1.22** to install successfully. Run the following command to get the repo: +`nuclei` requires **go1.23** to install successfully. Run the following command to get the repo: ```sh go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest From b03c30418bafbe43685ba25125ecb1d124e97203 Mon Sep 17 00:00:00 2001 From: circleous <20841686+circleous@users.noreply.github.com> Date: Thu, 15 May 2025 18:16:49 +0700 Subject: [PATCH 010/135] fix: fallback set SNI to host if not specified when using socks proxy (#6218) --- pkg/protocols/http/httpclientpool/clientpool.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/protocols/http/httpclientpool/clientpool.go b/pkg/protocols/http/httpclientpool/clientpool.go index 3f10fcbab..5c1a91cb5 100644 --- a/pkg/protocols/http/httpclientpool/clientpool.go +++ b/pkg/protocols/http/httpclientpool/clientpool.go @@ -307,6 +307,14 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl if err != nil { return nil, err } + if tlsConfig.ServerName == "" { + // addr should be in form of host:port already set from canonicalAddr + host, _, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + tlsConfig.ServerName = host + } return tls.Client(conn, tlsConfig), nil } } From 2c1cd27e2c52fee46925699c710986209bf10cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Thu, 15 May 2025 19:42:20 +0700 Subject: [PATCH 011/135] update version --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index 3b4976586..147cf23a2 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.3` + Version = `v3.4.4` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From ef05aac4e506c4cb1aa7ec7a8e280f0e08f5c9c2 Mon Sep 17 00:00:00 2001 From: Spencer Heywood Date: Thu, 15 May 2025 08:40:27 -0600 Subject: [PATCH 012/135] bump golang in dockerfile: 1.22 => 1.23 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9d7a780c7..1c44e7056 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build -FROM golang:1.22-alpine AS builder +FROM golang:1.23-alpine AS builder RUN apk add build-base WORKDIR /app @@ -13,4 +13,4 @@ FROM alpine:latest RUN apk add --no-cache bind-tools chromium ca-certificates COPY --from=builder /app/bin/nuclei /usr/local/bin/ -ENTRYPOINT ["nuclei"] \ No newline at end of file +ENTRYPOINT ["nuclei"] From 740a3732af27711873eac282fbaea7c0d98b9574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Thu, 15 May 2025 21:46:06 +0700 Subject: [PATCH 013/135] update dockerfile golang version --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9d7a780c7..c07c2fc57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build -FROM golang:1.22-alpine AS builder +FROM golang:1.23-alpine AS builder RUN apk add build-base WORKDIR /app From ebab60f9cdaa47c8fd2711d332b07527add88382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Thu, 15 May 2025 21:48:45 +0700 Subject: [PATCH 014/135] Revert "update dockerfile golang version" This reverts commit 740a3732af27711873eac282fbaea7c0d98b9574. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c07c2fc57..9d7a780c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build -FROM golang:1.23-alpine AS builder +FROM golang:1.22-alpine AS builder RUN apk add build-base WORKDIR /app From 39572371996f1502bf0813a41116db666e5c39b9 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 17 May 2025 02:16:41 +0700 Subject: [PATCH 015/135] fix(openapi): handles nil schema & schema values (#6228) Signed-off-by: Dwi Siswanto --- pkg/input/formats/openapi/examples.go | 30 ++++++++++++++++++++++++++ pkg/input/formats/openapi/generator.go | 28 +++++++++++++++--------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/pkg/input/formats/openapi/examples.go b/pkg/input/formats/openapi/examples.go index 9e7224ab7..235f940c9 100644 --- a/pkg/input/formats/openapi/examples.go +++ b/pkg/input/formats/openapi/examples.go @@ -288,3 +288,33 @@ func openAPIExample(schema *openapi3.Schema, cache map[*openapi3.Schema]*cachedS func generateExampleFromSchema(schema *openapi3.Schema) (interface{}, error) { return openAPIExample(schema, make(map[*openapi3.Schema]*cachedSchema)) // TODO: Use caching } + +func generateEmptySchemaValue(contentType string) *openapi3.Schema { + schema := &openapi3.Schema{} + objectType := &openapi3.Types{"object"} + stringType := &openapi3.Types{"string"} + + switch contentType { + case "application/json": + schema.Type = objectType + schema.Properties = make(map[string]*openapi3.SchemaRef) + case "application/xml": + schema.Type = stringType + schema.Format = "xml" + schema.Example = "" + case "text/plain": + schema.Type = stringType + case "application/x-www-form-urlencoded": + schema.Type = objectType + schema.Properties = make(map[string]*openapi3.SchemaRef) + case "multipart/form-data": + schema.Type = objectType + schema.Properties = make(map[string]*openapi3.SchemaRef) + case "application/octet-stream": + default: + schema.Type = stringType + schema.Format = "binary" + } + + return schema +} diff --git a/pkg/input/formats/openapi/generator.go b/pkg/input/formats/openapi/generator.go index 9c44797dc..1906858cb 100644 --- a/pkg/input/formats/openapi/generator.go +++ b/pkg/input/formats/openapi/generator.go @@ -268,24 +268,32 @@ func generateRequestsFromOp(opts *generateReqOptions) error { for content, value := range opts.op.RequestBody.Value.Content { cloned := req.Clone(req.Context()) - example, err := generateExampleFromSchema(value.Schema.Value) - if err != nil { - continue + var val interface{} + + if value.Schema == nil || value.Schema.Value == nil { + val = generateEmptySchemaValue(content) + } else { + var err error + + val, err = generateExampleFromSchema(value.Schema.Value) + if err != nil { + continue + } } // var body string switch content { case "application/json": - if marshalled, err := json.Marshal(example); err == nil { + if marshalled, err := json.Marshal(val); err == nil { // body = string(marshalled) cloned.Body = io.NopCloser(bytes.NewReader(marshalled)) cloned.ContentLength = int64(len(marshalled)) cloned.Header.Set("Content-Type", "application/json") } case "application/xml": - exampleVal := mxj.Map(example.(map[string]interface{})) + values := mxj.Map(val.(map[string]interface{})) - if marshalled, err := exampleVal.Xml(); err == nil { + if marshalled, err := values.Xml(); err == nil { // body = string(marshalled) cloned.Body = io.NopCloser(bytes.NewReader(marshalled)) cloned.ContentLength = int64(len(marshalled)) @@ -294,7 +302,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error { gologger.Warning().Msgf("openapi: could not encode xml") } case "application/x-www-form-urlencoded": - if values, ok := example.(map[string]interface{}); ok { + if values, ok := val.(map[string]interface{}); ok { cloned.Form = url.Values{} for k, v := range values { cloned.Form.Set(k, types.ToString(v)) @@ -306,7 +314,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error { cloned.Header.Set("Content-Type", "application/x-www-form-urlencoded") } case "multipart/form-data": - if values, ok := example.(map[string]interface{}); ok { + if values, ok := val.(map[string]interface{}); ok { buffer := &bytes.Buffer{} multipartWriter := multipart.NewWriter(buffer) for k, v := range values { @@ -326,13 +334,13 @@ func generateRequestsFromOp(opts *generateReqOptions) error { cloned.Header.Set("Content-Type", multipartWriter.FormDataContentType()) } case "text/plain": - str := types.ToString(example) + str := types.ToString(val) // body = str cloned.Body = io.NopCloser(strings.NewReader(str)) cloned.ContentLength = int64(len(str)) cloned.Header.Set("Content-Type", "text/plain") case "application/octet-stream": - str := types.ToString(example) + str := types.ToString(val) if str == "" { // use two strings str = "string1\nstring2" From 21d376f19478148bd3f1941db35e776a3d427294 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Sun, 18 May 2025 19:46:14 +0700 Subject: [PATCH 016/135] ci: adds stale workflow Signed-off-by: Dwi Siswanto --- .github/stale.yml | 27 ------------------------ .github/workflows/stale.yaml | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 27 deletions(-) delete mode 100644 .github/stale.yml create mode 100644 .github/workflows/stale.yaml diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 75d7ee029..000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,27 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 7 - -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 - -# Issues with these labels will never be considered stale -# exemptLabels: -# - pinned -# - security - -# Only issues or pull requests with all of these labels are check if stale. -onlyLabels: - - "Status: Abandoned" - - "Type: Question" - -# Label to use when marking as stale -staleLabel: stale - -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. - -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false \ No newline at end of file diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 000000000..2b336b671 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,41 @@ +name: 💤 Stale + +on: + schedule: + - cron: '0 0 * * 0' # Weekly + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write # only for delete-branch option + issues: write + pull-requests: write + steps: + - uses: actions/stale@v9 + with: + days-before-stale: 90 + days-before-close: 7 + stale-issue-label: "Status: Stale" + stale-pr-label: "Status: Stale" + stale-issue-message: > + This issue has been automatically marked as stale because it has not + had recent activity. It will be closed in 7 days if no further + activity occurs. Thank you for your contributions! + stale-pr-message: > + This pull request has been automatically marked as stale due to + inactivity. It will be closed in 7 days if no further activity + occurs. Please update if you wish to keep it open. + close-issue-message: > + This issue has been automatically closed due to inactivity. If you + think this is a mistake or would like to continue the discussion, + please comment or feel free to reopen it. + close-pr-message: > + This pull request has been automatically closed due to inactivity. + If you think this is a mistake or would like to continue working on + it, please comment or feel free to reopen it. + close-issue-label: "Status: Abandoned" + close-pr-label: "Status: Abandoned" + exempt-issue-labels: "Status: Abandoned" + exempt-pr-labels: "Status: Abandoned" From 242b1e1636ac80e2dc43ed071cb6ea6c6ee72a51 Mon Sep 17 00:00:00 2001 From: Nakul Bharti Date: Sun, 18 May 2025 20:09:41 +0530 Subject: [PATCH 017/135] increase file descriptor limits (#6230) * add missing file * increase file descriptor limit * removed debugging code * fixed lower case * test: tweaks on script * uses CI runtime env vars (`RUNNER_OS` & `RUNNER_DEBUG`) * restores originial `ulimit` Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto Co-authored-by: Dwi Siswanto --- .github/workflows/tests.yaml | 2 +- cmd/functional-test/main.go | 2 +- cmd/functional-test/run.sh | 42 +++++++++++++++++++++++++----------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index af6ad9d7e..7cbfd2f12 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -94,7 +94,7 @@ jobs: - uses: actions/checkout@v4 - uses: projectdiscovery/actions/setup/go@v1 - uses: projectdiscovery/actions/setup/python@v1 - - run: bash run.sh "${{ matrix.os }}" + - run: bash run.sh env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" working-directory: cmd/functional-test/ diff --git a/cmd/functional-test/main.go b/cmd/functional-test/main.go index 8a5cebc59..78114fdb3 100644 --- a/cmd/functional-test/main.go +++ b/cmd/functional-test/main.go @@ -27,7 +27,7 @@ var ( func main() { flag.Parse() - debug := os.Getenv("DEBUG") == "true" + debug := os.Getenv("DEBUG") == "true" || os.Getenv("RUNNER_DEBUG") == "1" if err, errored := runFunctionalTests(debug); err != nil { log.Fatalf("Could not run functional tests: %s\n", err) diff --git a/cmd/functional-test/run.sh b/cmd/functional-test/run.sh index a3caf7222..a955ad8a7 100755 --- a/cmd/functional-test/run.sh +++ b/cmd/functional-test/run.sh @@ -1,27 +1,43 @@ #!/bin/bash -# reading os type from arguments -CURRENT_OS=$1 +if [ "${RUNNER_OS}" == "Windows" ]; then + EXT=".exe" +elif [ "${RUNNER_OS}" == "macOS" ]; then + if [ "${CI}" == "true" ]; then + sudo sysctl -w kern.maxfiles{,perproc}=524288 + sudo launchctl limit maxfiles 65536 524288 + fi -if [ "${CURRENT_OS}" == "windows-latest" ];then - extension=.exe + ORIGINAL_ULIMIT="$(ulimit -n)" + ulimit -n 65536 || true fi +mkdir -p .nuclei-config/nuclei/ +touch .nuclei-config/nuclei/.nuclei-ignore + echo "::group::Building functional-test binary" -go build -o functional-test$extension +go build -o "functional-test${EXT}" echo "::endgroup::" echo "::group::Building Nuclei binary from current branch" -go build -o nuclei_dev$extension ../nuclei -echo "::endgroup::" - -echo "::group::Installing nuclei templates" -./nuclei_dev$extension -update-templates +go build -o "nuclei-dev${EXT}" ../nuclei echo "::endgroup::" echo "::group::Building latest release of nuclei" -go build -o nuclei$extension -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei +go build -o "nuclei${EXT}" -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei echo "::endgroup::" -echo 'Starting Nuclei functional test' -./functional-test$extension -main ./nuclei$extension -dev ./nuclei_dev$extension -testcases testcases.txt +echo "::group::Installing nuclei templates" +eval "./nuclei-dev${EXT} -update-templates" +echo "::endgroup::" + +echo "::group::Validating templates" +eval "./nuclei-dev${EXT} -validate" +echo "::endgroup::" + +echo "Starting Nuclei functional test" +eval "./functional-test${EXT} -main ./nuclei${EXT} -dev ./nuclei-dev${EXT} -testcases testcases.txt" + +if [ "${RUNNER_OS}" == "macOS" ]; then + ulimit -n "${ORIGINAL_ULIMIT}" || true +fi From 8a13639b624aa66e54e0cbe9a2e0be0a7303a1e2 Mon Sep 17 00:00:00 2001 From: Reynaldo Jarro Date: Tue, 27 May 2025 02:02:25 -0700 Subject: [PATCH 018/135] fixing missing symbol (#6242) --- README.md | 2 +- README_CN.md | 2 +- README_ES.md | 2 +- README_ID.md | 2 +- README_JP.md | 2 +- README_KR.md | 2 +- README_PT-BR.md | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1153b8e1c..741ceafc3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ `Korean``Indonesia``Spanish` • - `日本語` + `日本語``Portuguese` diff --git a/README_CN.md b/README_CN.md index f09622d65..99f150e6e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,7 +33,7 @@ 中文KoreanIndonesia • - Spanish + SpanishPortuguese

diff --git a/README_ES.md b/README_ES.md index 527ca7cdc..27f60ee8b 100644 --- a/README_ES.md +++ b/README_ES.md @@ -31,7 +31,7 @@ 中文KoreanIndonesia • - Spanish + SpanishPortuguese

diff --git a/README_ID.md b/README_ID.md index 1180c2ee8..05c163c23 100644 --- a/README_ID.md +++ b/README_ID.md @@ -33,7 +33,7 @@ 中文KoreanIndonesia • - Spanish + SpanishPortuguese

diff --git a/README_JP.md b/README_JP.md index a7fc7a0ac..d80fb4dfc 100644 --- a/README_JP.md +++ b/README_JP.md @@ -30,7 +30,7 @@ 中国語韓国語インドネシア語 • - スペイン語 + スペイン語ポルトガル語

diff --git a/README_KR.md b/README_KR.md index f1a27f00e..c59825cdb 100644 --- a/README_KR.md +++ b/README_KR.md @@ -31,7 +31,7 @@ English中文한국어 • - 스페인어 + 스페인어포르투갈어

diff --git a/README_PT-BR.md b/README_PT-BR.md index cff85180f..012f878f7 100644 --- a/README_PT-BR.md +++ b/README_PT-BR.md @@ -31,7 +31,7 @@ 中文KoreanIndonesia • - Spanish + SpanishPortuguese

From 3be29abfc96ad906fef679bf2f8c15688f081eac Mon Sep 17 00:00:00 2001 From: tongjicoder Date: Tue, 27 May 2025 17:16:26 +0800 Subject: [PATCH 019/135] refactor: use slices.Contains to simplify code Signed-off-by: tongjicoder --- pkg/catalog/aws/catalog.go | 7 +++---- pkg/catalog/aws/catalog_test.go | 9 ++------- pkg/catalog/config/nucleiconfig.go | 8 ++------ pkg/input/formats/openapi/examples.go | 9 ++------- pkg/protocols/http/request_condition.go | 8 ++------ 5 files changed, 11 insertions(+), 30 deletions(-) diff --git a/pkg/catalog/aws/catalog.go b/pkg/catalog/aws/catalog.go index 5dfa86a56..58d409360 100644 --- a/pkg/catalog/aws/catalog.go +++ b/pkg/catalog/aws/catalog.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "path" + "slices" "strings" "github.com/aws/aws-sdk-go-v2/aws" @@ -140,10 +141,8 @@ func (c Catalog) ResolvePath(templateName, second string) (string, error) { } // check if templateName is already an absolute path to c key - for _, key := range keys { - if key == templateName { - return templateName, nil - } + if slices.Contains(keys, templateName) { + return templateName, nil } return "", fmt.Errorf("no such path found: %s%s for keys: %v", second, templateName, keys) diff --git a/pkg/catalog/aws/catalog_test.go b/pkg/catalog/aws/catalog_test.go index 57dac391a..59095d635 100644 --- a/pkg/catalog/aws/catalog_test.go +++ b/pkg/catalog/aws/catalog_test.go @@ -3,6 +3,7 @@ package aws import ( "io" "reflect" + "slices" "strings" "testing" @@ -250,13 +251,7 @@ func (m mocks3svc) getAllKeys() ([]string, error) { } func (m mocks3svc) downloadKey(name string) (io.ReadCloser, error) { - found := false - for _, key := range m.keys { - if key == name { - found = true - break - } - } + found := slices.Contains(m.keys, name) if !found { return nil, errors.New("key not found") } diff --git a/pkg/catalog/config/nucleiconfig.go b/pkg/catalog/config/nucleiconfig.go index a7bb0ba23..246870935 100644 --- a/pkg/catalog/config/nucleiconfig.go +++ b/pkg/catalog/config/nucleiconfig.go @@ -7,6 +7,7 @@ import ( "log" "os" "path/filepath" + "slices" "strings" "github.com/projectdiscovery/goflags" @@ -334,12 +335,7 @@ func (c *Config) copyIgnoreFile() { // this could be a feature specific to debugging like PPROF or printing stats // of max host error etc func (c *Config) IsDebugArgEnabled(arg string) bool { - for _, v := range c.debugArgs { - if v == arg { - return true - } - } - return false + return slices.Contains(c.debugArgs, arg) } // parseDebugArgs from string diff --git a/pkg/input/formats/openapi/examples.go b/pkg/input/formats/openapi/examples.go index 235f940c9..2c79d5c89 100644 --- a/pkg/input/formats/openapi/examples.go +++ b/pkg/input/formats/openapi/examples.go @@ -2,6 +2,7 @@ package openapi import ( "fmt" + "slices" "github.com/getkin/kin-openapi/openapi3" "github.com/pkg/errors" @@ -84,13 +85,7 @@ func excludeFromMode(schema *openapi3.Schema) bool { // isRequired checks whether a key is actually required. func isRequired(schema *openapi3.Schema, key string) bool { - for _, req := range schema.Required { - if req == key { - return true - } - } - - return false + return slices.Contains(schema.Required, key) } type cachedSchema struct { diff --git a/pkg/protocols/http/request_condition.go b/pkg/protocols/http/request_condition.go index 50f881322..e92541443 100644 --- a/pkg/protocols/http/request_condition.go +++ b/pkg/protocols/http/request_condition.go @@ -2,6 +2,7 @@ package http import ( "regexp" + "slices" ) var ( @@ -32,10 +33,5 @@ func (request *Request) NeedsRequestCondition() bool { } func checkRequestConditionExpressions(expressions ...string) bool { - for _, expression := range expressions { - if reRequestCondition.MatchString(expression) { - return true - } - } - return false + return slices.ContainsFunc(expressions, reRequestCondition.MatchString) } From ec353f534cadaae7135951459f10c1d840d949ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Tue, 27 May 2025 21:42:33 +0900 Subject: [PATCH 020/135] bump dsl pkg --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7ed4bc989..23ff55738 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,7 @@ require ( github.com/microsoft/go-mssqldb v1.6.0 github.com/ory/dockertest/v3 v3.10.0 github.com/praetorian-inc/fingerprintx v1.1.9 - github.com/projectdiscovery/dsl v0.4.2 + github.com/projectdiscovery/dsl v0.4.3 github.com/projectdiscovery/fasttemplate v0.0.2 github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb github.com/projectdiscovery/goflags v0.1.74 diff --git a/go.sum b/go.sum index 964bb991d..3c80d1e5d 100644 --- a/go.sum +++ b/go.sum @@ -860,6 +860,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.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI= github.com/projectdiscovery/dsl v0.4.2/go.mod h1:J1RizRF6O3lvk2v8p/tLAYqaxWg6N52OWc+uS5ZmO2U= +github.com/projectdiscovery/dsl v0.4.3 h1:ZrbRkyK38hRiYMX7s6ohaTorDpq321ErqJuBUDmh49g= +github.com/projectdiscovery/dsl v0.4.3/go.mod h1:cyt2IaYhS5SlyZ1D2BdK0QwIBXQW/u9zaBmRAKYKAmk= github.com/projectdiscovery/fastdialer v0.4.0 h1:licZKyq+Shd5lLDb8uPd60Jp43K4NFE8cr67XD2eg7w= github.com/projectdiscovery/fastdialer v0.4.0/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ= github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA= From a0bd3b854ef8f3246b31384aa0d600be73320622 Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Thu, 12 Jun 2025 15:03:33 +0200 Subject: [PATCH 021/135] feat(templating): add vars templating into yaml inputs --- cmd/nuclei/main.go | 1 + go.mod | 8 ++- go.sum | 7 ++ pkg/input/formats/formats.go | 4 ++ .../formats/testdata/ginandjuice.ytt.yaml | 26 +++++++ pkg/input/formats/yaml/multidoc.go | 44 +++++++++--- pkg/input/formats/yaml/multidoc_test.go | 43 ++++++++++++ pkg/input/formats/yaml/ytt.go | 69 +++++++++++++++++++ pkg/input/provider/interface.go | 1 + pkg/types/types.go | 2 + 10 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 pkg/input/formats/testdata/ginandjuice.ytt.yaml create mode 100644 pkg/input/formats/yaml/ytt.go diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 8cc2b53f1..e1a3bfb1c 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -260,6 +260,7 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.StringVarP(&options.InputFileMode, "input-mode", "im", "list", fmt.Sprintf("mode of input file (%v)", provider.SupportedInputFormats())), flagSet.BoolVarP(&options.FormatUseRequiredOnly, "required-only", "ro", false, "use only required fields in input format when generating requests"), flagSet.BoolVarP(&options.SkipFormatValidation, "skip-format-validation", "sfv", false, "skip format validation (like missing vars) when parsing input file"), + flagSet.BoolVarP(&options.VarsTextTemplating, "vars-text-templating", "vtt", false, "enable text templating for vars in input file (only for yaml input mode)"), ) flagSet.CreateGroup("templates", "Templates", diff --git a/go.mod b/go.mod index 23ff55738..80b35383f 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/projectdiscovery/nuclei/v3 -go 1.23.0 +go 1.24.2 -toolchain go1.24.1 +toolchain go1.24.3 require ( github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible @@ -119,6 +119,7 @@ require ( require ( aead.dev/minisign v0.2.0 // indirect + carvel.dev/ytt v0.52.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect @@ -184,7 +185,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect @@ -194,6 +195,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect + github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 // indirect github.com/kataras/jwt v0.1.10 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/pgzip v1.2.6 // indirect diff --git a/go.sum b/go.sum index 3c80d1e5d..222127cdf 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk= aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ= +carvel.dev/ytt v0.52.0 h1:tkJPL8Gun5snVfypNXbmMKwnbwMyspcTi3Ypyso3nRY= +carvel.dev/ytt v0.52.0/go.mod h1:QgmuU7E15EXW1r2wxTt7zExVz14IHwEG4WNMmaFBkJo= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -577,6 +579,8 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -652,6 +656,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 h1:4bcRTTSx+LKSxMWibIwzHnDNmaN1x52oEpvnjCy+8vk= +github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368/go.mod h1:lKGj1op99m4GtQISxoD2t+K+WO/q2NzEPKvfXFQfbCA= github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ= github.com/kataras/jwt v0.1.10/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= @@ -1386,6 +1392,7 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/input/formats/formats.go b/pkg/input/formats/formats.go index 03c65d3fe..a23ff5d06 100644 --- a/pkg/input/formats/formats.go +++ b/pkg/input/formats/formats.go @@ -28,6 +28,10 @@ type InputFormatOptions struct { // RequiredOnly only uses required fields when generating requests // instead of all fields RequiredOnly bool + // VarsTextTemplating uses Variables and inject it into the input + // this is used for text templating of variables based on carvel ytt + // Only available for Yaml formats + VarsTextTemplating bool } // Format is an interface implemented by all input formats diff --git a/pkg/input/formats/testdata/ginandjuice.ytt.yaml b/pkg/input/formats/testdata/ginandjuice.ytt.yaml new file mode 100644 index 000000000..f1889a67f --- /dev/null +++ b/pkg/input/formats/testdata/ginandjuice.ytt.yaml @@ -0,0 +1,26 @@ +#@ load("@ytt:data", "data") +#@ load("@ytt:assert", "assert") + +#@ def get_value(key, default=""): +#@ if hasattr(data.values, key): +#@ value = getattr(data.values, key) +#@ return str(value) +#@ else: +#@ return default +#@ end +#@ end + +timestamp: 2024-02-20T19:24:13+05:32 +url: https://ginandjuice.shop/users/3 +request: + #@yaml/text-templated-strings + raw: |+ + POST /users/3 HTTP/1.1 + Host: ginandjuice.shop + Authorization: Bearer 3x4mpl3t0k3n + Accept-Encoding: gzip + Content-Type: application/x-www-form-urlencoded + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 + + foo=(@= get_value("foo") @)&bar=(@= get_value("bar") @) \ No newline at end of file diff --git a/pkg/input/formats/yaml/multidoc.go b/pkg/input/formats/yaml/multidoc.go index 6d75e0334..a6ae8067a 100644 --- a/pkg/input/formats/yaml/multidoc.go +++ b/pkg/input/formats/yaml/multidoc.go @@ -46,23 +46,47 @@ func (j *YamlMultiDocFormat) SetOptions(options formats.InputFormatOptions) { // Parse parses the input and calls the provided callback // function for each RawRequest it discovers. func (j *YamlMultiDocFormat) Parse(input io.Reader, resultsCb formats.ParseReqRespCallback, filePath string) error { - decoder := YamlUtil.NewDecoder(input) + finalInput := input + + // Apply text templating if enabled + if j.opts.VarsTextTemplating { + data, err := io.ReadAll(input) + if err != nil { + return errors.Wrap(err, "could not read input") + } + tpl := []string{string(data)} + dvs := mapToKeyValueSlice(j.opts.Variables) + finalInput, err = ytt(tpl, dvs) + if err != nil { + return errors.Wrap(err, "could not apply ytt templating") + } + finalData, err := io.ReadAll(finalInput) + if err != nil { + return errors.Wrap(err, "could not read templated input") + } + gologger.Debug().Msgf("Templated YAML content: %s", string(finalData)) + finalInput = strings.NewReader(string(finalData)) + + } + + decoder := YamlUtil.NewDecoder(finalInput) for { var request proxifyRequest - err := decoder.Decode(&request) - if err == io.EOF { - break + if err := decoder.Decode(&request); err != nil { + if err == io.EOF { + break + } + return errors.Wrap(err, "could not decode yaml file") } - if err != nil { - return errors.Wrap(err, "could not decode json file") - } - if strings.TrimSpace(request.Request.Raw) == "" { + + raw := strings.TrimSpace(request.Request.Raw) + if raw == "" { continue } - rawRequest, err := types.ParseRawRequestWithURL(request.Request.Raw, request.URL) + rawRequest, err := types.ParseRawRequestWithURL(raw, request.URL) if err != nil { - gologger.Warning().Msgf("multidoc-yaml: Could not parse raw request %s: %s\n", request.URL, err) + gologger.Warning().Msgf("multidoc-yaml: Could not parse raw request %s: %s", request.URL, err) continue } resultsCb(rawRequest) diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go index 0b91e774a..063d0f13c 100644 --- a/pkg/input/formats/yaml/multidoc_test.go +++ b/pkg/input/formats/yaml/multidoc_test.go @@ -4,6 +4,7 @@ import ( "os" "testing" + "github.com/projectdiscovery/nuclei/v3/pkg/input/formats" "github.com/projectdiscovery/nuclei/v3/pkg/input/types" "github.com/stretchr/testify/require" ) @@ -31,3 +32,45 @@ func TestYamlFormatterParse(t *testing.T) { require.Len(t, urls, len(expectedUrls), "invalid number of urls") require.ElementsMatch(t, urls, expectedUrls, "invalid urls") } + +func TestYamlFormatterParseWithVariables(t *testing.T) { + format := New() + proxifyYttFile := "../testdata/ginandjuice.ytt.yaml" + + expectedUrls := []string{ + "https://ginandjuice.shop/users/3", + } + + format.SetOptions(formats.InputFormatOptions{ + VarsTextTemplating: true, + Variables: map[string]interface{}{ + "foo": "catalog", + "bar": "product", + }, + }) + file, err := os.Open(proxifyYttFile) + require.Nilf(t, err, "error opening proxify ytt input file: %v", err) + defer file.Close() + + var urls []string + err = format.Parse(file, func(request *types.RequestResponse) bool { + urls = append(urls, request.URL.String()) + expectedRaw := `POST /users/3 HTTP/1.1 +Host: ginandjuice.shop +Authorization: Bearer 3x4mpl3t0k3n +Accept-Encoding: gzip +Content-Type: application/x-www-form-urlencoded +Connection: close +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 + +foo=catalog&bar=product` + require.Equal(t, expectedRaw, request.Request.Raw, "request raw does not match expected value") + + return false + }, proxifyYttFile) + + require.Nilf(t, err, "error parsing yaml file: %v", err) + require.Len(t, urls, len(expectedUrls), "invalid number of urls") + require.ElementsMatch(t, urls, expectedUrls, "invalid urls") + +} diff --git a/pkg/input/formats/yaml/ytt.go b/pkg/input/formats/yaml/ytt.go new file mode 100644 index 000000000..8bbaea752 --- /dev/null +++ b/pkg/input/formats/yaml/ytt.go @@ -0,0 +1,69 @@ +package yaml + +import ( + "bytes" + "fmt" + "io" + + yttcmd "carvel.dev/ytt/pkg/cmd/template" + yttui "carvel.dev/ytt/pkg/cmd/ui" + yttfiles "carvel.dev/ytt/pkg/files" +) + +func ytt(tpl, dvs []string) (io.Reader, error) { + // create and invoke ytt "template" command + templatingOptions := yttcmd.NewOptions() + + input, err := templatesAsInput(tpl...) + if err != nil { + return nil, err + } + + // equivalent to `--data-value-yaml` + templatingOptions.DataValuesFlags.KVsFromYAML = dvs + + // for in-memory use, pipe output to "/dev/null" + noopUI := yttui.NewCustomWriterTTY(false, noopWriter{}, noopWriter{}) + + // Evaluate the template given the configured data values... + output := templatingOptions.RunWithFiles(input, noopUI) + if output.Err != nil { + return nil, output.Err + } + + // output.DocSet contains the full set of resulting YAML documents, in order. + bs, err := output.DocSet.AsBytes() + if err != nil { + return nil, err + } + return bytes.NewReader(bs), nil +} + +// templatesAsInput conveniently wraps one or more strings, each in a files.File, into a template.Input. +func templatesAsInput(tpl ...string) (yttcmd.Input, error) { + var files []*yttfiles.File + for i, t := range tpl { + // to make this less brittle, you'll probably want to use well-defined names for `path`, here, for each input. + // this matters when you're processing errors which report based on these paths. + file, err := yttfiles.NewFileFromSource(yttfiles.NewBytesSource(fmt.Sprintf("tpl%d.yml", i), []byte(t))) + if err != nil { + return yttcmd.Input{}, err + } + + files = append(files, file) + } + + return yttcmd.Input{Files: files}, nil +} + +func mapToKeyValueSlice(m map[string]interface{}) []string { + var result []string + for k, v := range m { + result = append(result, fmt.Sprintf("%s=%v", k, v)) + } + return result +} + +type noopWriter struct{} + +func (w noopWriter) Write(data []byte) (int, error) { return len(data), nil } diff --git a/pkg/input/provider/interface.go b/pkg/input/provider/interface.go index e6d5da14a..769af60fb 100644 --- a/pkg/input/provider/interface.go +++ b/pkg/input/provider/interface.go @@ -116,6 +116,7 @@ func NewInputProvider(opts InputOptions) (InputProvider, error) { Variables: generators.MergeMaps(extraVars, opts.Options.Vars.AsMap()), SkipFormatValidation: opts.Options.SkipFormatValidation, RequiredOnly: opts.Options.FormatUseRequiredOnly, + VarsTextTemplating: opts.Options.VarsTextTemplating, }, }) } diff --git a/pkg/types/types.go b/pkg/types/types.go index 41c95ef68..5b71225cb 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -419,6 +419,8 @@ type Options struct { FormatUseRequiredOnly bool // SkipFormatValidation is used to skip format validation SkipFormatValidation bool + // VarsTextTemplating is used to inject variables into yaml input files + VarsTextTemplating bool // PayloadConcurrency is the number of concurrent payloads to run per template PayloadConcurrency int // ProbeConcurrency is the number of concurrent http probes to run with httpx From 5f501da06365934023e1cba5d9fd2db1d9162aef Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Thu, 12 Jun 2025 15:44:11 +0200 Subject: [PATCH 022/135] fix: enhance code rabbit --- go.mod | 2 +- go.sum | 10 ++++++---- pkg/input/formats/yaml/multidoc.go | 1 - pkg/input/formats/yaml/multidoc_test.go | 4 +++- pkg/input/formats/yaml/ytt.go | 5 ++++- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 80b35383f..3d60b4efe 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( ) require ( + carvel.dev/ytt v0.52.0 code.gitea.io/sdk/gitea v0.17.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 @@ -119,7 +120,6 @@ require ( require ( aead.dev/minisign v0.2.0 // indirect - carvel.dev/ytt v0.52.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect diff --git a/go.sum b/go.sum index 222127cdf..4dcdb0f46 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/gostackparse v0.6.0 h1:egCGQviIabPwsyoWpGvIBGrEnNWez35aEO7OJ1vBI4o= github.com/DataDog/gostackparse v0.6.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= @@ -515,6 +517,8 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -577,8 +581,6 @@ github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/C github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -656,6 +658,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/k14s/difflib v0.0.0-20201117154628-0c031775bf57 h1:CwBRArr+BWBopnUJhDjJw86rPL/jGbEjfHWKzTasSqE= +github.com/k14s/difflib v0.0.0-20201117154628-0c031775bf57/go.mod h1:B0xN2MiNBGWOWi9CcfAo9LBI8IU4J1utlbOIJCsmKr4= github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 h1:4bcRTTSx+LKSxMWibIwzHnDNmaN1x52oEpvnjCy+8vk= github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368/go.mod h1:lKGj1op99m4GtQISxoD2t+K+WO/q2NzEPKvfXFQfbCA= github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ= @@ -864,8 +868,6 @@ github.com/projectdiscovery/cdncheck v1.1.17 h1:YSqKk05+UGSxmPIp7tlCvRegF63FUqO+ github.com/projectdiscovery/cdncheck v1.1.17/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= -github.com/projectdiscovery/dsl v0.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI= -github.com/projectdiscovery/dsl v0.4.2/go.mod h1:J1RizRF6O3lvk2v8p/tLAYqaxWg6N52OWc+uS5ZmO2U= github.com/projectdiscovery/dsl v0.4.3 h1:ZrbRkyK38hRiYMX7s6ohaTorDpq321ErqJuBUDmh49g= github.com/projectdiscovery/dsl v0.4.3/go.mod h1:cyt2IaYhS5SlyZ1D2BdK0QwIBXQW/u9zaBmRAKYKAmk= github.com/projectdiscovery/fastdialer v0.4.0 h1:licZKyq+Shd5lLDb8uPd60Jp43K4NFE8cr67XD2eg7w= diff --git a/pkg/input/formats/yaml/multidoc.go b/pkg/input/formats/yaml/multidoc.go index a6ae8067a..679707672 100644 --- a/pkg/input/formats/yaml/multidoc.go +++ b/pkg/input/formats/yaml/multidoc.go @@ -64,7 +64,6 @@ func (j *YamlMultiDocFormat) Parse(input io.Reader, resultsCb formats.ParseReqRe if err != nil { return errors.Wrap(err, "could not read templated input") } - gologger.Debug().Msgf("Templated YAML content: %s", string(finalData)) finalInput = strings.NewReader(string(finalData)) } diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go index 063d0f13c..3064e8a7d 100644 --- a/pkg/input/formats/yaml/multidoc_test.go +++ b/pkg/input/formats/yaml/multidoc_test.go @@ -2,6 +2,7 @@ package yaml import ( "os" + "strings" "testing" "github.com/projectdiscovery/nuclei/v3/pkg/input/formats" @@ -64,7 +65,8 @@ Connection: close User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 foo=catalog&bar=product` - require.Equal(t, expectedRaw, request.Request.Raw, "request raw does not match expected value") + normalised := strings.ReplaceAll(request.Request.Raw, "\r\n", "\n") + require.Equal(t, expectedRaw, strings.TrimSuffix(normalised, "\n"), "request raw does not match expected value") return false }, proxifyYttFile) diff --git a/pkg/input/formats/yaml/ytt.go b/pkg/input/formats/yaml/ytt.go index 8bbaea752..c075119ca 100644 --- a/pkg/input/formats/yaml/ytt.go +++ b/pkg/input/formats/yaml/ytt.go @@ -4,10 +4,12 @@ import ( "bytes" "fmt" "io" + "strings" yttcmd "carvel.dev/ytt/pkg/cmd/template" yttui "carvel.dev/ytt/pkg/cmd/ui" yttfiles "carvel.dev/ytt/pkg/files" + "gopkg.in/yaml.v2" ) func ytt(tpl, dvs []string) (io.Reader, error) { @@ -59,7 +61,8 @@ func templatesAsInput(tpl ...string) (yttcmd.Input, error) { func mapToKeyValueSlice(m map[string]interface{}) []string { var result []string for k, v := range m { - result = append(result, fmt.Sprintf("%s=%v", k, v)) + y, _ := yaml.Marshal(v) + result = append(result, fmt.Sprintf("%s=%s", k, strings.TrimSpace(string(y)))) } return result } From 3eb3f668971b2732f0714befe12abb2ba6690840 Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Fri, 13 Jun 2025 13:59:24 +0200 Subject: [PATCH 023/135] fix: change gologger runner version --- internal/runner/runner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 424d27116..365e708db 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -863,8 +863,8 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) { return fmt.Sprintf("Current %s version: %v %v", versionType, version, updateutils.GetVersionDescription(version, latestVersion)) } - gologger.Info().Msgf(versionInfo(config.Version, cfg.LatestNucleiVersion, "nuclei")) - gologger.Info().Msgf(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates")) + gologger.Info().Msg(versionInfo(config.Version, cfg.LatestNucleiVersion, "nuclei")) + gologger.Info().Msg(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates")) if !HideAutoSaveMsg { if r.pdcpUploadErrMsg != "" { gologger.Print().Msgf("%s", r.pdcpUploadErrMsg) From fc6d5a7773e0d35263472f7c1d582ce1de7ad572 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:06:17 +0530 Subject: [PATCH 024/135] improved logging --- pkg/core/executors.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/core/executors.go b/pkg/core/executors.go index 2e8c4d18d..05430233b 100644 --- a/pkg/core/executors.go +++ b/pkg/core/executors.go @@ -38,7 +38,7 @@ func (e *Engine) executeAllSelfContained(ctx context.Context, alltemplates []*te match, err = template.Executer.Execute(ctx) } if err != nil { - gologger.Warning().Msgf("[%s] Could not execute step: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err) + gologger.Warning().Msgf("[%s] Could not execute step (self-contained): %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err) } results.CompareAndSwap(false, match) }(v) @@ -140,7 +140,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ } } if err != nil { - gologger.Warning().Msgf("[%s] Could not execute step: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err) + gologger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) } results.CompareAndSwap(false, match) }(index, skip, scannedValue) @@ -206,7 +206,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t } } if err != nil { - gologger.Warning().Msgf("[%s] Could not execute step: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err) + gologger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) } results.CompareAndSwap(false, match) }(tpl, target, sg) From f89a6d33e97c07220a0f3121cdb57cd88b0b97ef Mon Sep 17 00:00:00 2001 From: Shubham Rasal Date: Mon, 16 Jun 2025 22:24:52 +0530 Subject: [PATCH 025/135] Use proxy for dns and ssl templates (#6255) * Use proxy for dns and ssl templates - while using template execute level function we need to override custom dialer * rename overridedialer to customdialer * Add proxy into hash - proxy client is shared between non proxy requests * add dialer into request object - use request.dialer instead of global variable * resolve comments * rename dialer --- pkg/protocols/dns/dns.go | 1 + pkg/protocols/dns/dnsclientpool/clientpool.go | 10 +++++++++- pkg/protocols/http/http.go | 12 ++++++++++++ pkg/protocols/http/request.go | 6 +++--- pkg/protocols/network/network.go | 8 +++----- .../network/networkclientpool/clientpool.go | 9 ++++++++- pkg/protocols/network/request.go | 8 ++++++-- pkg/protocols/protocols.go | 3 +++ pkg/protocols/ssl/ssl.go | 4 +++- pkg/protocols/websocket/websocket.go | 4 +++- 10 files changed, 51 insertions(+), 14 deletions(-) diff --git a/pkg/protocols/dns/dns.go b/pkg/protocols/dns/dns.go index d6f462c44..198bb87bd 100644 --- a/pkg/protocols/dns/dns.go +++ b/pkg/protocols/dns/dns.go @@ -185,6 +185,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { func (request *Request) getDnsClient(options *protocols.ExecutorOptions, metadata map[string]interface{}) (*retryabledns.Client, error) { dnsClientOptions := &dnsclientpool.Configuration{ Retries: request.Retries, + Proxy: options.Options.AliveSocksProxy, } if len(request.Resolvers) > 0 { if len(request.Resolvers) > 0 { diff --git a/pkg/protocols/dns/dnsclientpool/clientpool.go b/pkg/protocols/dns/dnsclientpool/clientpool.go index 4f019808f..8eb19b8ba 100644 --- a/pkg/protocols/dns/dnsclientpool/clientpool.go +++ b/pkg/protocols/dns/dnsclientpool/clientpool.go @@ -51,6 +51,8 @@ type Configuration struct { Retries int // Resolvers contains the specific per request resolvers Resolvers []string + // Proxy contains the proxy to use for the dns client + Proxy string } // Hash returns the hash of the configuration to allow client pooling @@ -60,6 +62,8 @@ func (c *Configuration) Hash() string { builder.WriteString(strconv.Itoa(c.Retries)) builder.WriteString("l") builder.WriteString(strings.Join(c.Resolvers, "")) + builder.WriteString("p") + builder.WriteString(c.Proxy) hash := builder.String() return hash } @@ -83,7 +87,11 @@ func Get(options *types.Options, configuration *Configuration) (*retryabledns.Cl } else if len(configuration.Resolvers) > 0 { resolvers = configuration.Resolvers } - client, err := retryabledns.New(resolvers, configuration.Retries) + client, err := retryabledns.NewWithOptions(retryabledns.Options{ + BaseResolvers: resolvers, + MaxRetries: configuration.Retries, + Proxy: options.AliveSocksProxy, + }) if err != nil { return nil, errors.Wrap(err, "could not create dns client") } diff --git a/pkg/protocols/http/http.go b/pkg/protocols/http/http.go index 0b30a7408..7a45fcd0d 100644 --- a/pkg/protocols/http/http.go +++ b/pkg/protocols/http/http.go @@ -11,6 +11,7 @@ import ( json "github.com/json-iterator/go" "github.com/pkg/errors" + "github.com/projectdiscovery/fastdialer/fastdialer" _ "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/analyzers/time" "github.com/projectdiscovery/nuclei/v3/pkg/fuzz" @@ -22,6 +23,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/httpclientpool" + "github.com/projectdiscovery/nuclei/v3/pkg/protocols/network/networkclientpool" httputil "github.com/projectdiscovery/nuclei/v3/pkg/protocols/utils/http" "github.com/projectdiscovery/nuclei/v3/pkg/utils/stats" "github.com/projectdiscovery/rawhttp" @@ -144,6 +146,7 @@ type Request struct { generator *generators.PayloadGenerator // optional, only enabled when using payloads httpClient *retryablehttp.Client rawhttpClient *rawhttp.Client + dialer *fastdialer.Dialer // description: | // SelfContained specifies if the request is self-contained. @@ -348,6 +351,15 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { } request.customHeaders = make(map[string]string) request.httpClient = client + + dialer, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{ + CustomDialer: options.CustomFastdialer, + }) + if err != nil { + return errors.Wrap(err, "could not get dialer") + } + request.dialer = dialer + request.options = options for _, option := range request.options.Options.CustomHeaders { parts := strings.SplitN(option, ":", 2) diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index 6d8ad3e1d..090de2ed6 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -841,7 +841,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ if input.MetaInput.CustomIP != "" { outputEvent["ip"] = input.MetaInput.CustomIP } else { - outputEvent["ip"] = protocolstate.Dialer.GetDialedIP(hostname) + outputEvent["ip"] = request.dialer.GetDialedIP(hostname) // try getting cname request.addCNameIfAvailable(hostname, outputEvent) } @@ -1085,11 +1085,11 @@ func (request *Request) validateNFixEvent(input *contextargs.Context, gr *genera // addCNameIfAvailable adds the cname to the event if available func (request *Request) addCNameIfAvailable(hostname string, outputEvent map[string]interface{}) { - if protocolstate.Dialer == nil { + if request.dialer == nil { return } - data, err := protocolstate.Dialer.GetDNSData(hostname) + data, err := request.dialer.GetDNSData(hostname) if err == nil { switch len(data.CNAME) { case 0: diff --git a/pkg/protocols/network/network.go b/pkg/protocols/network/network.go index 5c072affc..7aba6244a 100644 --- a/pkg/protocols/network/network.go +++ b/pkg/protocols/network/network.go @@ -237,7 +237,9 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { } // Create a client for the class - client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{}) + client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{ + CustomDialer: options.CustomFastdialer, + }) if err != nil { return errors.Wrap(err, "could not get network client") } @@ -259,7 +261,3 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { func (request *Request) Requests() int { return len(request.Address) } - -func (request *Request) SetDialer(dialer *fastdialer.Dialer) { - request.dialer = dialer -} diff --git a/pkg/protocols/network/networkclientpool/clientpool.go b/pkg/protocols/network/networkclientpool/clientpool.go index a67cee296..6293a931e 100644 --- a/pkg/protocols/network/networkclientpool/clientpool.go +++ b/pkg/protocols/network/networkclientpool/clientpool.go @@ -21,7 +21,9 @@ func Init(options *types.Options) error { } // Configuration contains the custom configuration options for a client -type Configuration struct{} +type Configuration struct { + CustomDialer *fastdialer.Dialer +} // Hash returns the hash of the configuration to allow client pooling func (c *Configuration) Hash() string { @@ -30,5 +32,10 @@ func (c *Configuration) Hash() string { // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration /*TODO review unused parameters*/) (*fastdialer.Dialer, error) { + + if configuration != nil && configuration.CustomDialer != nil { + return configuration.CustomDialer, nil + } + return normalClient, nil } diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index f7b11fbb5..197ef5332 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -25,9 +25,9 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/eventcreator" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/helpers/responsehighlighter" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/interactsh" - "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump" + "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" errorutil "github.com/projectdiscovery/utils/errors" @@ -64,7 +64,11 @@ func (request *Request) getOpenPorts(target *contextargs.Context) ([]string, err errs = append(errs, err) continue } - conn, err := protocolstate.Dialer.Dial(target.Context(), "tcp", addr) + if request.dialer == nil { + request.dialer, _ = networkclientpool.Get(request.options.Options, &networkclientpool.Configuration{}) + } + + conn, err := request.dialer.Dial(target.Context(), "tcp", addr) if err != nil { errs = append(errs, err) continue diff --git a/pkg/protocols/protocols.go b/pkg/protocols/protocols.go index 7b7f71d48..6b5c089be 100644 --- a/pkg/protocols/protocols.go +++ b/pkg/protocols/protocols.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "sync/atomic" + "github.com/projectdiscovery/fastdialer/fastdialer" "github.com/projectdiscovery/ratelimit" mapsutil "github.com/projectdiscovery/utils/maps" stringsutil "github.com/projectdiscovery/utils/strings" @@ -132,6 +133,8 @@ type ExecutorOptions struct { ExportReqURLPattern bool // GlobalMatchers is the storage for global matchers with http passive templates GlobalMatchers *globalmatchers.Storage + // CustomFastdialer is a fastdialer dialer instance + CustomFastdialer *fastdialer.Dialer } // todo: centralizing components is not feasible with current clogged architecture diff --git a/pkg/protocols/ssl/ssl.go b/pkg/protocols/ssl/ssl.go index fd0dae83d..8943d597d 100644 --- a/pkg/protocols/ssl/ssl.go +++ b/pkg/protocols/ssl/ssl.go @@ -115,7 +115,9 @@ func (request *Request) IsClusterable() bool { func (request *Request) Compile(options *protocols.ExecutorOptions) error { request.options = options - client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{}) + client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{ + CustomDialer: options.CustomFastdialer, + }) if err != nil { return errorutil.NewWithTag("ssl", "could not get network client").Wrap(err) } diff --git a/pkg/protocols/websocket/websocket.go b/pkg/protocols/websocket/websocket.go index 8eeeedf21..02cf75190 100644 --- a/pkg/protocols/websocket/websocket.go +++ b/pkg/protocols/websocket/websocket.go @@ -100,7 +100,9 @@ const ( func (request *Request) Compile(options *protocols.ExecutorOptions) error { request.options = options - client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{}) + client, err := networkclientpool.Get(options.Options, &networkclientpool.Configuration{ + CustomDialer: options.CustomFastdialer, + }) if err != nil { return errors.Wrap(err, "could not get network client") } From 797ceb57dbc1600acf6f90bcc5becee99b5cd377 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Tue, 17 Jun 2025 06:18:05 +0700 Subject: [PATCH 026/135] fix(authx): JSON unmarshalling for Dynamic auth type (#6268) * fix(authx): JSON unmarshalling for Dynamic auth type Correcting the `UnmarshalJSON` method to properly unmarshal JSON, particularlyaddressing the population of the embedded `Secret` field. This was achieved by using a type alias to avoid recursive calls and rely on default unmarshalling behavior. Signed-off-by: Dwi Siswanto * feat(authx): adds nil Dynamic struct check Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- pkg/authprovider/authx/dynamic.go | 17 ++-- pkg/authprovider/authx/dynamic_test.go | 125 +++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 pkg/authprovider/authx/dynamic_test.go diff --git a/pkg/authprovider/authx/dynamic.go b/pkg/authprovider/authx/dynamic.go index 0efee1ea6..f3e361e41 100644 --- a/pkg/authprovider/authx/dynamic.go +++ b/pkg/authprovider/authx/dynamic.go @@ -52,14 +52,19 @@ func (d *Dynamic) GetDomainAndDomainRegex() ([]string, []string) { } func (d *Dynamic) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, &d); err != nil { + if d == nil { + return errorutil.New("cannot unmarshal into nil Dynamic struct") + } + + // Use an alias type (auxiliary) to avoid a recursive call in this method. + type Alias Dynamic + + // If d.Secret was nil, json.Unmarshal will allocate a new Secret object + // and populate it from the top level JSON fields. + if err := json.Unmarshal(data, (*Alias)(d)); err != nil { return err } - var s Secret - if err := json.Unmarshal(data, &s); err != nil { - return err - } - d.Secret = &s + return nil } diff --git a/pkg/authprovider/authx/dynamic_test.go b/pkg/authprovider/authx/dynamic_test.go new file mode 100644 index 000000000..05bf9c134 --- /dev/null +++ b/pkg/authprovider/authx/dynamic_test.go @@ -0,0 +1,125 @@ +package authx + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDynamicUnmarshalJSON(t *testing.T) { + t.Run("basic-unmarshal", func(t *testing.T) { + data := []byte(`{ + "template": "test-template.yaml", + "variables": [ + { + "key": "username", + "value": "testuser" + } + ], + "secrets": [ + { + "type": "BasicAuth", + "domains": ["example.com"], + "username": "user1", + "password": "pass1" + } + ], + "type": "BasicAuth", + "domains": ["test.com"], + "username": "testuser", + "password": "testpass" + }`) + + var d Dynamic + err := d.UnmarshalJSON(data) + require.NoError(t, err) + + // Secret + require.NotNil(t, d.Secret) + require.Equal(t, "BasicAuth", d.Secret.Type) + require.Equal(t, []string{"test.com"}, d.Secret.Domains) + require.Equal(t, "testuser", d.Secret.Username) + require.Equal(t, "testpass", d.Secret.Password) + + // Dynamic fields + require.Equal(t, "test-template.yaml", d.TemplatePath) + require.Len(t, d.Variables, 1) + require.Equal(t, "username", d.Variables[0].Key) + require.Equal(t, "testuser", d.Variables[0].Value) + require.Len(t, d.Secrets, 1) + require.Equal(t, "BasicAuth", d.Secrets[0].Type) + require.Equal(t, []string{"example.com"}, d.Secrets[0].Domains) + require.Equal(t, "user1", d.Secrets[0].Username) + require.Equal(t, "pass1", d.Secrets[0].Password) + }) + + t.Run("complex-unmarshal", func(t *testing.T) { + data := []byte(`{ + "template": "test-template.yaml", + "variables": [ + { + "key": "token", + "value": "Bearer xyz" + } + ], + "secrets": [ + { + "type": "CookiesAuth", + "domains": ["example.com"], + "cookies": [ + { + "key": "session", + "value": "abc123" + } + ] + } + ], + "type": "HeadersAuth", + "domains": ["api.test.com"], + "headers": [ + { + "key": "X-API-Key", + "value": "secret-key" + } + ] + }`) + + var d Dynamic + err := d.UnmarshalJSON(data) + require.NoError(t, err) + + // Secret + require.NotNil(t, d.Secret) + require.Equal(t, "HeadersAuth", d.Secret.Type) + require.Equal(t, []string{"api.test.com"}, d.Secret.Domains) + require.Len(t, d.Secret.Headers, 1) + require.Equal(t, "X-API-Key", d.Secret.Headers[0].Key) + require.Equal(t, "secret-key", d.Secret.Headers[0].Value) + + // Dynamic fields + require.Equal(t, "test-template.yaml", d.TemplatePath) + require.Len(t, d.Variables, 1) + require.Equal(t, "token", d.Variables[0].Key) + require.Equal(t, "Bearer xyz", d.Variables[0].Value) + require.Len(t, d.Secrets, 1) + require.Equal(t, "CookiesAuth", d.Secrets[0].Type) + require.Equal(t, []string{"example.com"}, d.Secrets[0].Domains) + require.Len(t, d.Secrets[0].Cookies, 1) + require.Equal(t, "session", d.Secrets[0].Cookies[0].Key) + require.Equal(t, "abc123", d.Secrets[0].Cookies[0].Value) + }) + + t.Run("invalid-json", func(t *testing.T) { + data := []byte(`{invalid json}`) + var d Dynamic + err := d.UnmarshalJSON(data) + require.Error(t, err) + }) + + t.Run("empty-json", func(t *testing.T) { + data := []byte(`{}`) + var d Dynamic + err := d.UnmarshalJSON(data) + require.NoError(t, err) + }) +} From a326f3925c5a00c8d8c214cdf839bf8075fe0cbe Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Tue, 17 Jun 2025 06:23:32 +0700 Subject: [PATCH 027/135] fix(tmplexec): memory blowup in multiproto (#6258) * bugfix: fix memory blowup using previousEvent for multi-proto execution * refactor(tmplexec): uses supported protocol types Signed-off-by: Dwi Siswanto * add co-author Co-authored-by: Nakul Bharti Signed-off-by: Dwi Siswanto * refactor(tmplexec): mv builder inside loop scope Signed-off-by: Dwi Siswanto * refactor(tmplexec): skip existing keys in `FillPreviousEvent` The `FillPreviousEvent` func was modified to prevent overwriting/duplicating entries in the previous map. It now checks if a key `k` from `event.InternalEvent` already exists in the previous map. If it does, the key is skipped. This ensures that if `k` was already set (potentially w/o a prefix), it's not re-added with an `ID_` prefix. Additionally, keys in `event.InternalEvent` that already start with the current `ID_` prefix are also skipped to avoid redundant prefixing. This change simplifies the logic by removing the `reqTypeWithIndexRegex` and directly addresses the potential for duplicate / incorrectly prefixed keys when `event.InternalEvent` grows during protocol request execution. Signed-off-by: Dwi Siswanto * chore(tmplexec): naming convention, `ID` => `protoID` Signed-off-by: Dwi Siswanto * chore(tmplexec): it's request ID lol sorry Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto Co-authored-by: Ice3man Co-authored-by: Nakul Bharti --- pkg/tmplexec/generic/exec.go | 16 ++++----------- pkg/tmplexec/multiproto/multi.go | 14 ++----------- pkg/tmplexec/utils/utils.go | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 pkg/tmplexec/utils/utils.go diff --git a/pkg/tmplexec/generic/exec.go b/pkg/tmplexec/generic/exec.go index c017810e7..25f88262e 100644 --- a/pkg/tmplexec/generic/exec.go +++ b/pkg/tmplexec/generic/exec.go @@ -1,13 +1,13 @@ package generic import ( - "strings" "sync/atomic" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/scan" + "github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/utils" mapsutil "github.com/projectdiscovery/utils/maps" ) @@ -64,17 +64,9 @@ func (g *Generic) ExecuteWithResults(ctx *scan.ScanContext) error { // ideally this should never happen since protocol exits on error and callback is not called return } - ID := req.GetID() - if ID != "" { - builder := &strings.Builder{} - for k, v := range event.InternalEvent { - builder.WriteString(ID) - builder.WriteString("_") - builder.WriteString(k) - _ = previous.Set(builder.String(), v) - builder.Reset() - } - } + + utils.FillPreviousEvent(req.GetID(), event, previous) + if event.HasOperatorResult() { g.results.CompareAndSwap(false, true) } diff --git a/pkg/tmplexec/multiproto/multi.go b/pkg/tmplexec/multiproto/multi.go index d50e168ac..ef029861a 100644 --- a/pkg/tmplexec/multiproto/multi.go +++ b/pkg/tmplexec/multiproto/multi.go @@ -2,7 +2,6 @@ package multiproto import ( "strconv" - "strings" "sync/atomic" "github.com/projectdiscovery/nuclei/v3/pkg/output" @@ -10,6 +9,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" "github.com/projectdiscovery/nuclei/v3/pkg/scan" "github.com/projectdiscovery/nuclei/v3/pkg/templates/types" + "github.com/projectdiscovery/nuclei/v3/pkg/tmplexec/utils" mapsutil "github.com/projectdiscovery/utils/maps" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -90,17 +90,7 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error { return } - ID := req.GetID() - if ID != "" { - builder := &strings.Builder{} - for k, v := range event.InternalEvent { - builder.WriteString(ID) - builder.WriteString("_") - builder.WriteString(k) - _ = previous.Set(builder.String(), v) - builder.Reset() - } - } + utils.FillPreviousEvent(req.GetID(), event, previous) // log event and generate result for the event ctx.LogEvent(event) diff --git a/pkg/tmplexec/utils/utils.go b/pkg/tmplexec/utils/utils.go new file mode 100644 index 000000000..41d717769 --- /dev/null +++ b/pkg/tmplexec/utils/utils.go @@ -0,0 +1,34 @@ +package utils + +import ( + "strings" + + "github.com/projectdiscovery/nuclei/v3/pkg/output" + mapsutil "github.com/projectdiscovery/utils/maps" +) + +// FillPreviousEvent is a helper function to get the previous event from the event +// without leading to duplicate prefixes +func FillPreviousEvent(reqID string, event *output.InternalWrappedEvent, previous *mapsutil.SyncLockMap[string, any]) { + if reqID == "" { + return + } + + for k, v := range event.InternalEvent { + if _, ok := previous.Get(k); ok { + continue + } + + if strings.HasPrefix(k, reqID+"_") { + continue + } + + var builder strings.Builder + + builder.WriteString(reqID) + builder.WriteString("_") + builder.WriteString(k) + + _ = previous.Set(builder.String(), v) + } +} From 61bcf0f10ec8296b9aacc2165e91040ba1b3066f Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Tue, 17 Jun 2025 06:30:31 +0700 Subject: [PATCH 028/135] feat(headless): store responses (#6247) Signed-off-by: Dwi Siswanto --- pkg/protocols/headless/request.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/protocols/headless/request.go b/pkg/protocols/headless/request.go index af65c4b2f..22a33bf7f 100644 --- a/pkg/protocols/headless/request.go +++ b/pkg/protocols/headless/request.go @@ -223,10 +223,15 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p } func dumpResponse(event *output.InternalWrappedEvent, requestOptions *protocols.ExecutorOptions, responseBody string, input string) { - cliOptions := requestOptions.Options - if cliOptions.Debug || cliOptions.DebugResponse { - highlightedResponse := responsehighlighter.Highlight(event.OperatorsResult, responseBody, cliOptions.NoColor, false) - gologger.Debug().Msgf("[%s] Dumped Headless response for %s\n\n%s", requestOptions.TemplateID, input, highlightedResponse) + if requestOptions.Options.Debug || requestOptions.Options.DebugResponse || requestOptions.Options.StoreResponse { + msg := fmt.Sprintf("[%s] Dumped Headless response for %s\n\n", requestOptions.TemplateID, input) + if requestOptions.Options.Debug || requestOptions.Options.DebugResponse { + resp := responsehighlighter.Highlight(event.OperatorsResult, responseBody, requestOptions.Options.NoColor, false) + gologger.Debug().Msgf("%s%s", msg, resp) + } + if requestOptions.Options.StoreResponse { + requestOptions.Output.WriteStoreDebugData(input, requestOptions.TemplateID, "headless", fmt.Sprintf("%s%s", msg, responseBody)) + } } } From b95b04fc4dc300a6340d5d360437217f188ff594 Mon Sep 17 00:00:00 2001 From: Eric Gruber Date: Mon, 16 Jun 2025 18:38:01 -0500 Subject: [PATCH 029/135] feat: add EnableMatcherStatus function to configure matcher status in NucleiEngine (#6191) --- lib/config.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/config.go b/lib/config.go index 46df00aa2..f570a0729 100644 --- a/lib/config.go +++ b/lib/config.go @@ -463,6 +463,14 @@ func EnablePassiveMode() NucleiSDKOptions { } } +// EnableMatcherStatus allows enabling matcher status +func EnableMatcherStatus() NucleiSDKOptions { + return func(e *NucleiEngine) error { + e.opts.MatcherStatus = true + return nil + } +} + // WithAuthProvider allows setting a custom authprovider implementation func WithAuthProvider(provider authprovider.AuthProvider) NucleiSDKOptions { return func(e *NucleiEngine) error { From 5af6feb88958f1433dbc22bed5e6c7fa5daf3a14 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Tue, 17 Jun 2025 05:12:02 +0530 Subject: [PATCH 030/135] version update --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index 147cf23a2..f7036431a 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.4` + Version = `v3.4.5` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From aba8c47e10d165e33a966ecb6f270b334834b9fe Mon Sep 17 00:00:00 2001 From: knakul853 Date: Tue, 17 Jun 2025 17:02:57 +0530 Subject: [PATCH 031/135] fixed log level mismatch --- pkg/operators/common/dsl/dsl.go | 2 +- pkg/output/output.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/operators/common/dsl/dsl.go b/pkg/operators/common/dsl/dsl.go index 1b3a02bed..56ac06509 100644 --- a/pkg/operators/common/dsl/dsl.go +++ b/pkg/operators/common/dsl/dsl.go @@ -114,7 +114,7 @@ func init() { })) dsl.PrintDebugCallback = func(args ...interface{}) error { - gologger.Info().Msgf("print_debug value: %s", fmt.Sprint(args)) + gologger.Debug().Msgf("print_debug value: %s", fmt.Sprint(args)) return nil } diff --git a/pkg/output/output.go b/pkg/output/output.go index e85774b83..02b62f6e1 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -560,7 +560,7 @@ func (w *StandardWriter) WriteStoreDebugData(host, templateID, eventType string, filename = filepath.Join(subFolder, fmt.Sprintf("%s.txt", filename)) f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) if err != nil { - fmt.Print(err) + gologger.Error().Msgf("Could not open debug output file: %s", err) return } _, _ = f.WriteString(fmt.Sprintln(data)) From c242b112ccef37321144cb1d4a795a5d71255a15 Mon Sep 17 00:00:00 2001 From: Nakul Bharti Date: Thu, 19 Jun 2025 20:07:59 +0530 Subject: [PATCH 032/135] fixed hex dump issue (#6273) --- pkg/protocols/http/request.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index 090de2ed6..14599f690 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -1156,7 +1156,7 @@ func dumpResponse(event *output.InternalWrappedEvent, request *Request, redirect response := string(redirectedResponse) var highlightedResult string - if responseContentType == "application/octet-stream" || ((responseContentType == "" || responseContentType == "application/x-www-form-urlencoded") && responsehighlighter.HasBinaryContent(response)) { + if (responseContentType == "application/octet-stream" || responseContentType == "application/x-www-form-urlencoded") && responsehighlighter.HasBinaryContent(response) { highlightedResult = createResponseHexDump(event, response, cliOptions.NoColor) } else { highlightedResult = responsehighlighter.Highlight(event.OperatorsResult, response, cliOptions.NoColor, false) From 695a7520b976191bd814b48a4789265d7cbad3fa Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Tue, 24 Jun 2025 07:02:18 +0700 Subject: [PATCH 033/135] fix(headless): incorrect last navigated URL (#6278) * chore(headless): uses `maps.Copy` Signed-off-by: Dwi Siswanto * feat(headless): implements update last navigated URL for `ActionNavigate`, `WaitPageLifecycleEvent`, and `WaitStable` based on latest navigation URL. Signed-off-by: Dwi Siswanto * Update pkg/protocols/headless/engine/page.go --------- Signed-off-by: Dwi Siswanto --- pkg/protocols/headless/engine/page.go | 38 ++++++++++++------- pkg/protocols/headless/engine/page_actions.go | 21 ++++++++-- pkg/protocols/headless/request.go | 11 ++---- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index fd8687e14..4dca72a6a 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -24,19 +24,20 @@ import ( // Page is a single page in an isolated browser instance type Page struct { - ctx *contextargs.Context - inputURL *urlutil.URL - options *Options - page *rod.Page - rules []rule - instance *Instance - hijackRouter *rod.HijackRouter - hijackNative *Hijack - mutex *sync.RWMutex - History []HistoryData - InteractshURLs []string - payloads map[string]interface{} - variables map[string]interface{} + ctx *contextargs.Context + inputURL *urlutil.URL + options *Options + page *rod.Page + rules []rule + instance *Instance + hijackRouter *rod.HijackRouter + hijackNative *Hijack + mutex *sync.RWMutex + History []HistoryData + InteractshURLs []string + payloads map[string]interface{} + variables map[string]interface{} + lastActionNavigate *Action } // HistoryData contains the page request/response pairs @@ -274,6 +275,17 @@ func (p *Page) hasModificationRules() bool { return false } +// updateLastNavigatedURL updates the last navigated URL in the instance's +// request log. +func (p *Page) updateLastNavigatedURL() { + if p.lastActionNavigate == nil { + return + } + + templateURL := p.lastActionNavigate.GetArg("url") + p.instance.requestLog[templateURL] = p.URL() +} + func containsModificationActions(actions ...*Action) bool { for _, action := range actions { if containsAnyModificationActionType(action.ActionType.ActionType) { diff --git a/pkg/protocols/headless/engine/page_actions.go b/pkg/protocols/headless/engine/page_actions.go index a0b001daf..204ce8eea 100644 --- a/pkg/protocols/headless/engine/page_actions.go +++ b/pkg/protocols/headless/engine/page_actions.go @@ -47,6 +47,7 @@ const ( // ExecuteActions executes a list of actions on a page. func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action) (outData ActionData, err error) { outData = make(ActionData) + // waitFuncs are function that needs to be executed after navigation // typically used for waitEvent waitFuncs := make([]func() error, 0) @@ -76,6 +77,8 @@ func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action) (ou } } } + + p.lastActionNavigate = act } case ActionScript: err = p.RunScript(act, outData) @@ -407,12 +410,12 @@ func (p *Page) NavigateURL(action *Action, out ActionData) error { finalparams.Merge(p.inputURL.Params.Encode()) parsedURL.Params = finalparams - // log all navigated requests - p.instance.requestLog[action.GetArg("url")] = parsedURL.String() - if err := p.page.Navigate(parsedURL.String()); err != nil { return errorutil.NewWithErr(err).Msgf("could not navigate to url %s", parsedURL.String()) } + + p.updateLastNavigatedURL() + return nil } @@ -667,6 +670,9 @@ func (p *Page) WaitPageLifecycleEvent(act *Action, out ActionData, event proto.P fn() + // log the navigated request (even if it is a redirect) + p.updateLastNavigatedURL() + return nil } @@ -687,7 +693,14 @@ func (p *Page) WaitStable(act *Action, out ActionData) error { } } - return p.page.Timeout(timeout).WaitStable(dur) + if err := p.page.Timeout(timeout).WaitStable(dur); err != nil { + return err + } + + // log the navigated request (even if it is a redirect) + p.updateLastNavigatedURL() + + return nil } // GetResource gets a resource from an element from page. diff --git a/pkg/protocols/headless/request.go b/pkg/protocols/headless/request.go index 22a33bf7f..83280ee63 100644 --- a/pkg/protocols/headless/request.go +++ b/pkg/protocols/headless/request.go @@ -2,6 +2,7 @@ package headless import ( "fmt" + "maps" "net/url" "strings" "time" @@ -9,7 +10,6 @@ import ( "github.com/projectdiscovery/retryablehttp-go" "github.com/pkg/errors" - "golang.org/x/exp/maps" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/fuzz" @@ -189,12 +189,9 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p if request.options.HasTemplateCtx(input.MetaInput) { outputEvent = generators.MergeMaps(outputEvent, request.options.GetTemplateCtx(input.MetaInput).GetAll()) } - for k, v := range out { - outputEvent[k] = v - } - for k, v := range payloads { - outputEvent[k] = v - } + + maps.Copy(outputEvent, out) + maps.Copy(outputEvent, payloads) var event *output.InternalWrappedEvent if len(page.InteractshURLs) == 0 { From 4ff80784aed47212cb27c474eaad45f9ceed05ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E5=AE=B6=E5=B7=A7?= Date: Tue, 24 Jun 2025 08:19:06 +0800 Subject: [PATCH 034/135] refactor: use the built-in max/min to simplify the code (#6272) Signed-off-by: xiaoxiangirl --- cmd/integration-test/http.go | 5 +---- pkg/protocols/http/request.go | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/cmd/integration-test/http.go b/cmd/integration-test/http.go index be75506cb..f0e5d1ae2 100644 --- a/cmd/integration-test/http.go +++ b/cmd/integration-test/http.go @@ -829,10 +829,7 @@ func (h *httpPaths) Execute(filepath string) error { } if len(expected) > len(actual) { - actualValuesIndex := len(actual) - 1 - if actualValuesIndex < 0 { - actualValuesIndex = 0 - } + actualValuesIndex := max(len(actual)-1, 0) return fmt.Errorf("missing values : %v", expected[actualValuesIndex:]) } else if len(expected) < len(actual) { return fmt.Errorf("unexpected values : %v", actual[len(expected)-1:]) diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index 14599f690..f401fe4cf 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -336,11 +336,8 @@ func (request *Request) executeTurboHTTP(input *contextargs.Context, dynamicValu pipeClient := rawhttp.NewPipelineClient(pipeOptions) // defaultMaxWorkers should be a sufficient value to keep queues always full - maxWorkers := defaultMaxWorkers // in case the queue is bigger increase the workers - if pipeOptions.MaxPendingRequests > maxWorkers { - maxWorkers = pipeOptions.MaxPendingRequests - } + maxWorkers := max(pipeOptions.MaxPendingRequests, defaultMaxWorkers) // Stop-at-first-match logic while executing requests // parallely using threads From 248548e075db5822710c12a5336d8503e4c8e040 Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Tue, 24 Jun 2025 18:32:45 +0200 Subject: [PATCH 035/135] feat(ytt): add ytt files var + add vars from cli and config --- cmd/nuclei/main.go | 31 +++++++++++++++ integration_tests/fuzz/fuzz-body.yaml | 38 +++++++++++++++++++ pkg/input/formats/formats.go | 2 + .../testdata/{ => ytt}/ginandjuice.ytt.yaml | 9 ++--- .../formats/testdata/ytt/ytt-profile.yaml | 10 +++++ pkg/input/formats/testdata/ytt/ytt-vars.yaml | 3 ++ pkg/input/formats/yaml/multidoc.go | 2 +- pkg/input/formats/yaml/ytt.go | 7 +++- pkg/input/provider/interface.go | 1 + pkg/types/types.go | 2 + 10 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 integration_tests/fuzz/fuzz-body.yaml rename pkg/input/formats/testdata/{ => ytt}/ginandjuice.ytt.yaml (71%) create mode 100644 pkg/input/formats/testdata/ytt/ytt-profile.yaml create mode 100644 pkg/input/formats/testdata/ytt/ytt-vars.yaml diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index e1a3bfb1c..13fb0d69d 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -18,6 +18,7 @@ import ( "github.com/projectdiscovery/utils/env" _ "github.com/projectdiscovery/utils/pprof" stringsutil "github.com/projectdiscovery/utils/strings" + "gopkg.in/yaml.v2" "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/gologger" @@ -261,6 +262,7 @@ on extensive configurability, massive extensibility and ease of use.`) flagSet.BoolVarP(&options.FormatUseRequiredOnly, "required-only", "ro", false, "use only required fields in input format when generating requests"), flagSet.BoolVarP(&options.SkipFormatValidation, "skip-format-validation", "sfv", false, "skip format validation (like missing vars) when parsing input file"), flagSet.BoolVarP(&options.VarsTextTemplating, "vars-text-templating", "vtt", false, "enable text templating for vars in input file (only for yaml input mode)"), + flagSet.StringSliceVarP(&options.VarsFilePaths, "var-file-paths", "vfp", nil, "list of yaml file contained vars to inject into yaml input", goflags.CommaSeparatedStringSliceOptions), ) flagSet.CreateGroup("templates", "Templates", @@ -569,6 +571,7 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started config.DefaultConfig.SetConfigDir(customConfigDir) readFlagsConfig(flagSet) } + if cfgFile != "" { if !fileutil.FileExists(cfgFile) { gologger.Fatal().Msgf("given config file '%s' does not exist", cfgFile) @@ -577,6 +580,34 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started if err := flagSet.MergeConfigFile(cfgFile); err != nil { gologger.Fatal().Msgf("Could not read config: %s\n", err) } + + if !options.Vars.IsEmpty() { + // Maybe we should add vars to the config file as well? + file, err := os.Open(cfgFile) + if err != nil { + gologger.Fatal().Msgf("Could not open config file: %s\n", err) + } + defer file.Close() + data := make(map[string]interface{}) + err = yaml.NewDecoder(file).Decode(&data) + if err != nil { + gologger.Fatal().Msgf("Could not decode config file: %s\n", err) + } + + variables := data["var"] + if variables != nil { + for _, value := range variables.([]interface{}) { + if strVal, ok := value.(string); ok { + options.Vars.Set(strVal) + } else { + gologger.Warning().Msgf("Skipping non-string variable in config: %#v", value) + } + } + } else { + gologger.Warning().Msgf("No 'var' section found in config file: %s", cfgFile) + } + + } } if options.NewTemplatesDirectory != "" { config.DefaultConfig.SetTemplatesDir(options.NewTemplatesDirectory) diff --git a/integration_tests/fuzz/fuzz-body.yaml b/integration_tests/fuzz/fuzz-body.yaml new file mode 100644 index 000000000..01a3006f6 --- /dev/null +++ b/integration_tests/fuzz/fuzz-body.yaml @@ -0,0 +1,38 @@ +id: fuzz-body + +info: + name: fuzzing error sqli payloads in http req body + author: pdteam + severity: info + description: | + This template attempts to find SQL injection vulnerabilities by fuzzing http body + It automatically handles and parses json,xml,multipart form and x-www-form-urlencoded data + and performs fuzzing on the value of every key + +http: + - pre-condition: + - type: dsl + dsl: + - method != "GET" + - method != "HEAD" + condition: and + + payloads: + injection: + - "'" + - "\"" + - ";" + + fuzzing: + - part: body + type: postfix + mode: single + fuzz: + - '{{injection}}' + + stop-at-first-match: true + matchers: + - type: word + words: + - "unrecognized token:" + - "null" diff --git a/pkg/input/formats/formats.go b/pkg/input/formats/formats.go index a23ff5d06..acc6c31d4 100644 --- a/pkg/input/formats/formats.go +++ b/pkg/input/formats/formats.go @@ -32,6 +32,8 @@ type InputFormatOptions struct { // this is used for text templating of variables based on carvel ytt // Only available for Yaml formats VarsTextTemplating bool + // VarsFilePaths is the path to the file containing variables + VarsFilePaths []string } // Format is an interface implemented by all input formats diff --git a/pkg/input/formats/testdata/ginandjuice.ytt.yaml b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml similarity index 71% rename from pkg/input/formats/testdata/ginandjuice.ytt.yaml rename to pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml index f1889a67f..a43bca070 100644 --- a/pkg/input/formats/testdata/ginandjuice.ytt.yaml +++ b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml @@ -1,10 +1,9 @@ #@ load("@ytt:data", "data") -#@ load("@ytt:assert", "assert") +#@ load("@ytt:json", "json") #@ def get_value(key, default=""): #@ if hasattr(data.values, key): -#@ value = getattr(data.values, key) -#@ return str(value) +#@ return str(getattr(data.values, key)) #@ else: #@ return default #@ end @@ -17,10 +16,10 @@ request: raw: |+ POST /users/3 HTTP/1.1 Host: ginandjuice.shop - Authorization: Bearer 3x4mpl3t0k3n + Authorization: Bearer (@= get_value("token") @) Accept-Encoding: gzip Content-Type: application/x-www-form-urlencoded Connection: close User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 - foo=(@= get_value("foo") @)&bar=(@= get_value("bar") @) \ No newline at end of file + foo=(@= get_value("foo") @)&bar=(@= get_value("bar") @)&debug=(@= get_value("debug", "false") @) \ No newline at end of file diff --git a/pkg/input/formats/testdata/ytt/ytt-profile.yaml b/pkg/input/formats/testdata/ytt/ytt-profile.yaml new file mode 100644 index 000000000..2cad498bc --- /dev/null +++ b/pkg/input/formats/testdata/ytt/ytt-profile.yaml @@ -0,0 +1,10 @@ +list: pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml +input-mode: yaml +templates: + - integration_tests/fuzz/fuzz-body.yaml +var: + - debug=true +vars-text-templating: true +var-file-paths: + - pkg/input/formats/testdata/ytt/ytt-vars.yaml +dast: true \ No newline at end of file diff --git a/pkg/input/formats/testdata/ytt/ytt-vars.yaml b/pkg/input/formats/testdata/ytt/ytt-vars.yaml new file mode 100644 index 000000000..be973bee8 --- /dev/null +++ b/pkg/input/formats/testdata/ytt/ytt-vars.yaml @@ -0,0 +1,3 @@ +foo: tata +bar: foo +token: TOKEN-BEARER \ No newline at end of file diff --git a/pkg/input/formats/yaml/multidoc.go b/pkg/input/formats/yaml/multidoc.go index 679707672..1140d5509 100644 --- a/pkg/input/formats/yaml/multidoc.go +++ b/pkg/input/formats/yaml/multidoc.go @@ -56,7 +56,7 @@ func (j *YamlMultiDocFormat) Parse(input io.Reader, resultsCb formats.ParseReqRe } tpl := []string{string(data)} dvs := mapToKeyValueSlice(j.opts.Variables) - finalInput, err = ytt(tpl, dvs) + finalInput, err = ytt(tpl, dvs, j.opts.VarsFilePaths) if err != nil { return errors.Wrap(err, "could not apply ytt templating") } diff --git a/pkg/input/formats/yaml/ytt.go b/pkg/input/formats/yaml/ytt.go index c075119ca..3ccf5f6d2 100644 --- a/pkg/input/formats/yaml/ytt.go +++ b/pkg/input/formats/yaml/ytt.go @@ -12,7 +12,7 @@ import ( "gopkg.in/yaml.v2" ) -func ytt(tpl, dvs []string) (io.Reader, error) { +func ytt(tpl, dvs []string, varFiles []string) (io.Reader, error) { // create and invoke ytt "template" command templatingOptions := yttcmd.NewOptions() @@ -21,6 +21,11 @@ func ytt(tpl, dvs []string) (io.Reader, error) { return nil, err } + if len(varFiles) > 0 { + // Load vaarFiles into the templating options. + templatingOptions.DataValuesFlags.FromFiles = varFiles + } + // equivalent to `--data-value-yaml` templatingOptions.DataValuesFlags.KVsFromYAML = dvs diff --git a/pkg/input/provider/interface.go b/pkg/input/provider/interface.go index 769af60fb..c98214dd3 100644 --- a/pkg/input/provider/interface.go +++ b/pkg/input/provider/interface.go @@ -117,6 +117,7 @@ func NewInputProvider(opts InputOptions) (InputProvider, error) { SkipFormatValidation: opts.Options.SkipFormatValidation, RequiredOnly: opts.Options.FormatUseRequiredOnly, VarsTextTemplating: opts.Options.VarsTextTemplating, + VarsFilePaths: opts.Options.VarsFilePaths, }, }) } diff --git a/pkg/types/types.go b/pkg/types/types.go index 5b71225cb..47c434072 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -421,6 +421,8 @@ type Options struct { SkipFormatValidation bool // VarsTextTemplating is used to inject variables into yaml input files VarsTextTemplating bool + // VarsFilePaths is used to inject variables into yaml input files from a file + VarsFilePaths goflags.StringSlice // PayloadConcurrency is the number of concurrent payloads to run per template PayloadConcurrency int // ProbeConcurrency is the number of concurrent http probes to run with httpx From 1a9a7563c0c7f957d1cc8424ddc309b33af98126 Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Tue, 24 Jun 2025 18:39:29 +0200 Subject: [PATCH 036/135] feat: send struct from var file --- pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml | 2 +- pkg/input/formats/testdata/ytt/ytt-profile.yaml | 1 + pkg/input/formats/testdata/ytt/ytt-vars.yaml | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml index a43bca070..b409ad214 100644 --- a/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml +++ b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml @@ -22,4 +22,4 @@ request: Connection: close User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 - foo=(@= get_value("foo") @)&bar=(@= get_value("bar") @)&debug=(@= get_value("debug", "false") @) \ No newline at end of file + foo=(@= json.encode(data.values.foo) @)&bar=(@= get_value("bar") @)&debug=(@= get_value("debug", "false") @) \ No newline at end of file diff --git a/pkg/input/formats/testdata/ytt/ytt-profile.yaml b/pkg/input/formats/testdata/ytt/ytt-profile.yaml index 2cad498bc..01e794ad4 100644 --- a/pkg/input/formats/testdata/ytt/ytt-profile.yaml +++ b/pkg/input/formats/testdata/ytt/ytt-profile.yaml @@ -4,6 +4,7 @@ templates: - integration_tests/fuzz/fuzz-body.yaml var: - debug=true + - bar=bar vars-text-templating: true var-file-paths: - pkg/input/formats/testdata/ytt/ytt-vars.yaml diff --git a/pkg/input/formats/testdata/ytt/ytt-vars.yaml b/pkg/input/formats/testdata/ytt/ytt-vars.yaml index be973bee8..625ba7ddb 100644 --- a/pkg/input/formats/testdata/ytt/ytt-vars.yaml +++ b/pkg/input/formats/testdata/ytt/ytt-vars.yaml @@ -1,3 +1,3 @@ -foo: tata -bar: foo -token: TOKEN-BEARER \ No newline at end of file +token: foobar +foo: + bar: baz \ No newline at end of file From 99914e1a32f01a06c1e9781d99dcd22e4dd43853 Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Tue, 24 Jun 2025 18:45:35 +0200 Subject: [PATCH 037/135] fix code rabbit --- cmd/nuclei/main.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 13fb0d69d..a2663b505 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -582,7 +582,7 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started } if !options.Vars.IsEmpty() { - // Maybe we should add vars to the config file as well? + // Maybe we should add vars to the config file as well even if they are set via flags? file, err := os.Open(cfgFile) if err != nil { gologger.Fatal().Msgf("Could not open config file: %s\n", err) @@ -596,15 +596,17 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started variables := data["var"] if variables != nil { - for _, value := range variables.([]interface{}) { - if strVal, ok := value.(string); ok { - options.Vars.Set(strVal) - } else { - gologger.Warning().Msgf("Skipping non-string variable in config: %#v", value) + if varSlice, ok := variables.([]interface{}); ok { + for _, value := range varSlice { + if strVal, ok := value.(string); ok { + options.Vars.Set(strVal) + } else { + gologger.Warning().Msgf("Skipping non-string variable in config: %#v", value) + } } + } else { + gologger.Warning().Msgf("No 'var' section found in config file: %s", cfgFile) } - } else { - gologger.Warning().Msgf("No 'var' section found in config file: %s", cfgFile) } } From 3bcbcc6e652c469c03cf67573c794c05c716cf04 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Wed, 25 Jun 2025 00:03:44 +0700 Subject: [PATCH 038/135] test(nuclei): adds multiproto benchmark test (#6270) * test(nuclei): adds multiproto benchmark test Signed-off-by: Dwi Siswanto * test(nuclei): deferred runner close & rm duped `os.MkdirTemp` Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- .../{main_test.go => main_benchmark_test.go} | 74 ++++- .../basic-template-multiproto-mixed.yaml | 239 ++++++++++++++ .../basic-template-multiproto-raw.yaml | 292 ++++++++++++++++++ .../multiproto/basic-template-multiproto.yaml | 170 ++++++++++ 4 files changed, 762 insertions(+), 13 deletions(-) rename cmd/nuclei/{main_test.go => main_benchmark_test.go} (63%) create mode 100644 cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-mixed.yaml create mode 100644 cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-raw.yaml create mode 100644 cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto.yaml diff --git a/cmd/nuclei/main_test.go b/cmd/nuclei/main_benchmark_test.go similarity index 63% rename from cmd/nuclei/main_test.go rename to cmd/nuclei/main_benchmark_test.go index 01c75d5c8..baf9dbfab 100644 --- a/cmd/nuclei/main_test.go +++ b/cmd/nuclei/main_benchmark_test.go @@ -3,28 +3,56 @@ package main_test import ( "net/http" "net/http/httptest" + "os" "testing" "time" - "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/gologger/levels" "github.com/projectdiscovery/nuclei/v3/internal/runner" "github.com/projectdiscovery/nuclei/v3/pkg/types" ) -func BenchmarkRunEnumeration(b *testing.B) { +var ( + projectPath string + targetURL string +) + +func TestMain(m *testing.M) { + // Set up + + gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) + os.Setenv("DISABLE_STDOUT", "true") + + var err error + + projectPath, err = os.MkdirTemp("", "nuclei-benchmark-") + if err != nil { + panic(err) + } + dummyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) })) - defer dummyServer.Close() + targetURL = dummyServer.URL - options := &types.Options{ - RemoteTemplateDomainList: goflags.StringSlice{ - "cloud.projectdiscovery.io", - }, - ProjectPath: "/tmp", - Targets: goflags.StringSlice{dummyServer.URL}, + // Execute tests + + exitCode := m.Run() + + // Tear down + + dummyServer.Close() + _ = os.RemoveAll(projectPath) + os.Unsetenv("DISABLE_STDOUT") + + os.Exit(exitCode) +} + +func getDefaultOptions() *types.Options { + return &types.Options{ + RemoteTemplateDomainList: []string{"cloud.projectdiscovery.io"}, + ProjectPath: projectPath, StatsInterval: 5, MetricsPort: 9092, MaxHostError: 30, @@ -66,22 +94,42 @@ func BenchmarkRunEnumeration(b *testing.B) { // DialerKeepAlive: time.Duration(0), // DASTServerAddress: "localhost:9055", } +} +func runEnumBenchmark(b *testing.B, options *types.Options) { runner.ParseOptions(options) - // Disable logging to reduce benchmark noise. - gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) - nucleiRunner, err := runner.New(options) if err != nil { b.Fatalf("failed to create runner: %s", err) } + defer nucleiRunner.Close() b.ResetTimer() + b.ReportAllocs() for i := 0; i < b.N; i++ { if err := nucleiRunner.RunEnumeration(); err != nil { - b.Fatalf("RunEnumeration failed: %s", err) + b.Fatalf("%s failed: %s", b.Name(), err) } } } + +func BenchmarkRunEnumeration(b *testing.B) { + // Default case: run enumeration with default options == all nuclei-templates + // b.Run("Default", func(b *testing.B) { + // options := getDefaultOptions() + // options.Targets = []string{targetURL} + + // runEnumBenchmark(b, options) + // }) + + // Case: https://github.com/projectdiscovery/nuclei/pull/6258 + b.Run("Multiproto", func(b *testing.B) { + options := getDefaultOptions() + options.Targets = []string{targetURL} + options.Templates = []string{"./cmd/nuclei/testdata/benchmark/multiproto/"} + + runEnumBenchmark(b, options) + }) +} diff --git a/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-mixed.yaml b/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-mixed.yaml new file mode 100644 index 000000000..d11db6e2d --- /dev/null +++ b/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-mixed.yaml @@ -0,0 +1,239 @@ +id: basic-template-multiproto-mixed + +info: + name: Test Template Multiple Protocols (Mixed) + author: pdteam + severity: info + +http: + - method: GET + id: first_iter_http + path: + - '{{BaseURL}}/1' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/2' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/3' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/4' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/5' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/6' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/7' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/8' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/9' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /10 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /11 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /12 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /13 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /14 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET / HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /15 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /16 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /17 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /18 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" \ No newline at end of file diff --git a/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-raw.yaml b/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-raw.yaml new file mode 100644 index 000000000..f868fdc57 --- /dev/null +++ b/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto-raw.yaml @@ -0,0 +1,292 @@ +id: basic-template-multiproto-raw + +info: + name: Test Template Multiple Protocols RAW + author: pdteam + severity: info + +http: + - raw: + - | + GET /1 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /2 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /3 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /4 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /5 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /6 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /7 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /8 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /9 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /10 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /11 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /12 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /13 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /14 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET / HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /15 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /16 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /17 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" + + - raw: + - | + GET /18 HTTP/1.1 + Host: {{Hostname}} + Origin: {{BaseURL}} + Connection: close + User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) + Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 + Accept-Language: en-US,en;q=0.9 + + matchers: + - type: word + words: + - "Test is test matcher text" \ No newline at end of file diff --git a/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto.yaml b/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto.yaml new file mode 100644 index 000000000..6a7d37c86 --- /dev/null +++ b/cmd/nuclei/testdata/benchmark/multiproto/basic-template-multiproto.yaml @@ -0,0 +1,170 @@ +id: basic-template-multiproto + +info: + name: Test Template Multiple Protocols + author: pdteam + severity: info + +http: + - method: GET + id: first_iter_http + path: + - '{{BaseURL}}/1' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/2' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/3' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/4' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/5' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/6' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/7' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/8' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/9' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/10' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/11' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/12' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/13' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/14' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/15' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/16' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/17' + + matchers: + - type: word + words: + - "Test is test matcher text" + + - method: GET + path: + - '{{BaseURL}}/18' + + matchers: + - type: word + words: + - "Test is test matcher text" \ No newline at end of file From 2c3df33a9837c90f058f5019cdb09428f6590535 Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Wed, 25 Jun 2025 00:23:15 +0300 Subject: [PATCH 039/135] chore: update GoReleaser configurations (#6280) Signed-off-by: Emmanuel Ferdman --- .goreleaser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index d33aabc1f..2d2f61379 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -38,9 +38,9 @@ builds: # goarch: [amd64] archives: - - format: zip + - formats: [zip] id: nuclei - builds: [nuclei-cli] + ids: [nuclei-cli] name_template: '{{ .ProjectName }}_{{ .Version }}_{{ if eq .Os "darwin" }}macOS{{ else }}{{ .Os }}{{ end }}_{{ .Arch }}' checksum: From 937fa1252b6bb2bec051f4b9980e692188974ee7 Mon Sep 17 00:00:00 2001 From: Alban Stourbe Date: Thu, 26 Jun 2025 09:42:14 +0200 Subject: [PATCH 040/135] fix(main.go): add errcheck --- cmd/nuclei/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index a2663b505..2991fb81e 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -599,7 +599,10 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started if varSlice, ok := variables.([]interface{}); ok { for _, value := range varSlice { if strVal, ok := value.(string); ok { - options.Vars.Set(strVal) + err = options.Vars.Set(strVal) + if err != nil { + gologger.Warning().Msgf("Could not set variable from config file: %s\n", err) + } } else { gologger.Warning().Msgf("Skipping non-string variable in config: %#v", value) } From 7b1a02710eb21c7fceb0a654abd641a64e72d5bd Mon Sep 17 00:00:00 2001 From: Cho hyun-sik <78861124+1223v@users.noreply.github.com> Date: Sat, 28 Jun 2025 05:38:44 +0900 Subject: [PATCH 041/135] docs: refine Bug Bounty hunter section in Korean docs (#6287) --- README_KR.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_KR.md b/README_KR.md index c59825cdb..6181c866b 100644 --- a/README_KR.md +++ b/README_KR.md @@ -341,7 +341,7 @@ Nuclei를 사용하면 자체 검사 모음으로 테스트 접근 방식을 사 - 몇 분 안에 수천 개의 호스트를 처리할 수 있음. - 간단한 YAML DSL로 사용자 지정 테스트 접근 방식을 쉽게 자동화할 수 있음. -버그 바운티 워크플로에 맞는 다른 오픈 소스 프로젝트를 확인할 수 있습니다.: [github.com/projectdiscovery](http://github.com/projectdiscovery), 또한, 우리는 매일 [Chaos에서 DNS 데이터를 갱신해 호스팅합니다.](http://chaos.projectdiscovery.io). +버그 바운티 워크플로에 맞는 다른 오픈 소스 프로젝트를 확인할 수 있습니다.: [github.com/projectdiscovery](http://github.com/projectdiscovery), 또한, 우리는 매일 [Chaos에서 DNS 데이터를 갱신해 호스팅합니다](http://chaos.projectdiscovery.io). From 2b729e40373cc81c13ee104844b3839bbe96c559 Mon Sep 17 00:00:00 2001 From: Tarun Koyalwar <45962551+tarunKoyalwar@users.noreply.github.com> Date: Mon, 30 Jun 2025 15:13:00 +0530 Subject: [PATCH 042/135] fix context leak in flow (#6282) * fix context leak in flow * handle sizedwaitpool when not reused --- pkg/js/compiler/compiler.go | 24 +++++++++++++++++++++--- pkg/js/compiler/compiler_test.go | 2 +- pkg/protocols/code/code.go | 2 +- pkg/protocols/javascript/js.go | 6 +++--- pkg/tmplexec/exec.go | 2 +- pkg/tmplexec/flow/flow_executor.go | 7 ++++++- pkg/tmplexec/flow/vm.go | 10 +++++++--- 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/pkg/js/compiler/compiler.go b/pkg/js/compiler/compiler.go index b13e7f9ec..cd698e4a0 100644 --- a/pkg/js/compiler/compiler.go +++ b/pkg/js/compiler/compiler.go @@ -156,9 +156,27 @@ func (c *Compiler) ExecuteWithOptions(program *goja.Program, args *ExecuteArgs, return res, nil } -// Wraps a script in a function and compiles it. -func WrapScriptNCompile(script string, strict bool) (*goja.Program, error) { - if !stringsutil.ContainsAny(script, exportAsToken, exportToken) { +// if the script uses export/ExportAS tokens then we can run it in IIFE mode +// but if not we can't run it +func CanRunAsIIFE(script string) bool { + return stringsutil.ContainsAny(script, exportAsToken, exportToken) +} + +// SourceIIFEMode is a mode where the script is wrapped in a function and compiled. +// This is used when the script is not exported or exported as a function. +func SourceIIFEMode(script string, strict bool) (*goja.Program, error) { + val := fmt.Sprintf(` + (function() { + %s + })() + `, script) + return goja.Compile("", val, strict) +} + +// SourceAutoMode is a mode where the script is wrapped in a function and compiled. +// This is used when the script is exported or exported as a function. +func SourceAutoMode(script string, strict bool) (*goja.Program, error) { + if !CanRunAsIIFE(script) { // this will not be run in a pooled runtime return goja.Compile("", script, strict) } diff --git a/pkg/js/compiler/compiler_test.go b/pkg/js/compiler/compiler_test.go index 3a43a4016..01acb0d06 100644 --- a/pkg/js/compiler/compiler_test.go +++ b/pkg/js/compiler/compiler_test.go @@ -21,7 +21,7 @@ func TestNewCompilerConsoleDebug(t *testing.T) { }) compiler := New() - p, err := WrapScriptNCompile("console.log('hello world');", false) + p, err := SourceAutoMode("console.log('hello world');", false) if err != nil { t.Fatal(err) } diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index b3344d08d..1d687d235 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -130,7 +130,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { // compile pre-condition if any if request.PreCondition != "" { - preConditionCompiled, err := compiler.WrapScriptNCompile(request.PreCondition, false) + preConditionCompiled, err := compiler.SourceAutoMode(request.PreCondition, false) if err != nil { return errorutil.NewWithTag(request.TemplateID, "could not compile pre-condition: %s", err) } diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index 344199fb3..e8b9c0b38 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -215,7 +215,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { // proceed with whatever args we have args.Args, _ = request.evaluateArgs(allVars, options, true) - initCompiled, err := compiler.WrapScriptNCompile(request.Init, false) + initCompiled, err := compiler.SourceAutoMode(request.Init, false) if err != nil { return errorutil.NewWithTag(request.TemplateID, "could not compile init code: %s", err) } @@ -236,7 +236,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { // compile pre-condition if any if request.PreCondition != "" { - preConditionCompiled, err := compiler.WrapScriptNCompile(request.PreCondition, false) + preConditionCompiled, err := compiler.SourceAutoMode(request.PreCondition, false) if err != nil { return errorutil.NewWithTag(request.TemplateID, "could not compile pre-condition: %s", err) } @@ -245,7 +245,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { // compile actual source code if request.Code != "" { - scriptCompiled, err := compiler.WrapScriptNCompile(request.Code, false) + scriptCompiled, err := compiler.SourceAutoMode(request.Code, false) if err != nil { return errorutil.NewWithTag(request.TemplateID, "could not compile javascript code: %s", err) } diff --git a/pkg/tmplexec/exec.go b/pkg/tmplexec/exec.go index d0ed09331..c59b6c123 100644 --- a/pkg/tmplexec/exec.go +++ b/pkg/tmplexec/exec.go @@ -43,7 +43,7 @@ func NewTemplateExecuter(requests []protocols.Request, options *protocols.Execut // we use a dummy input here because goal of flow executor at this point is to just check // syntax and other things are correct before proceeding to actual execution // during execution new instance of flow will be created as it is tightly coupled with lot of executor options - p, err := compiler.WrapScriptNCompile(options.Flow, false) + p, err := compiler.SourceAutoMode(options.Flow, false) if err != nil { return nil, fmt.Errorf("could not compile flow: %s", err) } diff --git a/pkg/tmplexec/flow/flow_executor.go b/pkg/tmplexec/flow/flow_executor.go index 62112e0f8..a8c554679 100644 --- a/pkg/tmplexec/flow/flow_executor.go +++ b/pkg/tmplexec/flow/flow_executor.go @@ -8,6 +8,7 @@ import ( "sync/atomic" "github.com/dop251/goja" + "github.com/projectdiscovery/nuclei/v3/pkg/js/compiler" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" "github.com/projectdiscovery/nuclei/v3/pkg/scan" @@ -195,7 +196,11 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error { // get a new runtime from pool runtime := GetJSRuntime(f.options.Options) - defer PutJSRuntime(runtime) // put runtime back to pool + defer func() { + // whether to reuse or not depends on the whether script modifies + // global scope or not, + PutJSRuntime(runtime, compiler.CanRunAsIIFE(f.options.Flow)) + }() defer func() { // remove set builtin _ = runtime.GlobalObject().Delete("set") diff --git a/pkg/tmplexec/flow/vm.go b/pkg/tmplexec/flow/vm.go index f1f7dbb84..88033c250 100644 --- a/pkg/tmplexec/flow/vm.go +++ b/pkg/tmplexec/flow/vm.go @@ -35,7 +35,7 @@ func GetJSRuntime(opts *types.Options) *goja.Runtime { if opts.JsConcurrency < 100 { opts.JsConcurrency = 100 } - sizedgojapool, _ = sizedpool.New[*goja.Runtime]( + sizedgojapool, _ = sizedpool.New( sizedpool.WithPool[*goja.Runtime](gojapool), sizedpool.WithSize[*goja.Runtime](int64(opts.JsConcurrency)), ) @@ -45,8 +45,12 @@ func GetJSRuntime(opts *types.Options) *goja.Runtime { } // PutJSRuntime returns a JS runtime to pool -func PutJSRuntime(runtime *goja.Runtime) { - sizedgojapool.Put(runtime) +func PutJSRuntime(runtime *goja.Runtime, reuse bool) { + if reuse { + sizedgojapool.Put(runtime) + } else { + sizedgojapool.Put(gojapool.Get().(*goja.Runtime)) + } } func registerBuiltins(runtime *goja.Runtime) { From 87ed0b2bb93e8106ac06397db50f210156cf9816 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Tue, 1 Jul 2025 00:40:44 +0700 Subject: [PATCH 043/135] build: bump all direct modules (#6290) * chore: fix non-constant fmt string in call Signed-off-by: Dwi Siswanto * build: bump all direct modules Signed-off-by: Dwi Siswanto * chore(hosterrorscache): update import path Signed-off-by: Dwi Siswanto * fix(charts): break changes Signed-off-by: Dwi Siswanto * build: pinned `github.com/zmap/zcrypto` to v0.0.0-20240512203510-0fef58d9a9db Signed-off-by: Dwi Siswanto * chore: golangci-lint auto fixes Signed-off-by: Dwi Siswanto * chore: satisfy lints Signed-off-by: Dwi Siswanto * build: migrate `github.com/xanzy/go-gitlab` => `gitlab.com/gitlab-org/api/client-go` Signed-off-by: Dwi Siswanto * feat(json): update build constraints Signed-off-by: Dwi Siswanto * chore: dont panicking on close err Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- cmd/docgen/docgen.go | 4 +- cmd/functional-test/main.go | 4 +- cmd/generate-checksum/main.go | 4 +- cmd/integration-test/custom-dir.go | 4 +- cmd/integration-test/dsl.go | 4 +- cmd/integration-test/flow.go | 2 +- cmd/integration-test/fuzz.go | 10 +- cmd/integration-test/generic.go | 9 +- cmd/integration-test/headless.go | 8 +- cmd/integration-test/http.go | 94 +- cmd/integration-test/integration-test.go | 4 +- cmd/integration-test/library.go | 4 +- cmd/integration-test/loader.go | 32 +- cmd/integration-test/network.go | 28 +- cmd/integration-test/ssl.go | 24 +- cmd/integration-test/template-dir.go | 4 +- cmd/integration-test/workflow.go | 24 +- cmd/nuclei/main.go | 6 +- cmd/nuclei/main_benchmark_test.go | 4 +- cmd/tmc/main.go | 10 +- cmd/tools/fuzzplayground/main.go | 4 +- examples/with_speed_control/main.go | 3 +- go.mod | 410 +++---- go.sum | 1054 +++++------------ internal/pdcp/writer.go | 14 +- internal/runner/healthcheck.go | 6 +- internal/runner/options.go | 10 +- internal/runner/proxy.go | 11 +- internal/runner/runner.go | 10 +- internal/runner/runner_test.go | 24 +- internal/server/server.go | 2 +- pkg/authprovider/authx/dynamic.go | 8 +- pkg/authprovider/authx/dynamic_test.go | 14 +- pkg/catalog/config/ignorefile.go | 4 +- pkg/catalog/config/template.go | 4 +- pkg/catalog/loader/ai_loader.go | 4 +- pkg/catalog/loader/loader.go | 4 +- pkg/catalog/loader/remote_loader.go | 9 +- pkg/external/customtemplates/gitlab.go | 2 +- pkg/external/customtemplates/s3.go | 4 +- pkg/fuzz/analyzers/time/analyzer.go | 2 +- pkg/fuzz/analyzers/time/time_delay.go | 5 +- pkg/fuzz/component/path.go | 8 +- pkg/fuzz/component/path_test.go | 6 +- pkg/fuzz/component/query.go | 2 +- pkg/fuzz/component/query_test.go | 4 +- pkg/fuzz/dataformat/multipart.go | 6 +- pkg/fuzz/execute.go | 2 +- pkg/fuzz/parts.go | 2 +- pkg/fuzz/stats/stats.go | 5 +- pkg/input/formats/burp/burp_test.go | 4 +- pkg/input/formats/formats.go | 4 +- pkg/input/formats/json/json_test.go | 4 +- pkg/input/formats/openapi/generator.go | 8 +- pkg/input/formats/openapi/openapi_test.go | 4 +- pkg/input/formats/swagger/swagger_test.go | 4 +- pkg/input/formats/yaml/multidoc_test.go | 4 +- pkg/input/provider/http/multiformat.go | 2 +- pkg/input/provider/list/hmap.go | 4 +- pkg/input/transform_test.go | 4 +- pkg/installer/template_test.go | 6 +- pkg/installer/versioncheck.go | 4 +- pkg/installer/zipslip_unix_test.go | 4 +- pkg/js/devtools/bindgen/output.go | 20 +- pkg/js/libs/kerberos/sendtokdc.go | 16 +- pkg/js/libs/ldap/ldap.go | 11 +- pkg/js/libs/mssql/mssql.go | 12 +- pkg/js/libs/mysql/mysql.go | 12 +- pkg/js/libs/mysql/mysql_private.go | 4 +- pkg/js/libs/oracle/oracle.go | 4 +- pkg/js/libs/pop3/pop3.go | 4 +- pkg/js/libs/postgres/postgres.go | 16 +- pkg/js/libs/rdp/rdp.go | 8 +- pkg/js/libs/redis/redis.go | 20 +- pkg/js/libs/rsync/rsync.go | 4 +- pkg/js/libs/smb/smb.go | 8 +- pkg/js/libs/smb/smb_private.go | 4 +- pkg/js/libs/smb/smbghost.go | 4 +- pkg/js/libs/smtp/smtp.go | 8 +- pkg/js/libs/ssh/ssh.go | 8 +- pkg/js/libs/telnet/telnet.go | 4 +- pkg/js/libs/vnc/vnc.go | 4 +- pkg/js/utils/util.go | 4 +- pkg/operators/operators.go | 2 +- pkg/output/output.go | 16 +- pkg/progress/progress.go | 6 +- pkg/projectfile/project.go | 2 +- pkg/protocols/code/code.go | 8 +- .../common/automaticscan/automaticscan.go | 6 +- .../common/expressions/expressions.go | 6 +- pkg/protocols/common/generators/load.go | 4 +- .../common/hosterrorscache/hosterrorscache.go | 4 +- pkg/protocols/common/interactsh/interactsh.go | 8 +- pkg/protocols/common/randomip/randomip.go | 2 +- pkg/protocols/dns/cluster.go | 3 +- pkg/protocols/dns/dnsclientpool/clientpool.go | 2 +- pkg/protocols/dns/operators.go | 2 +- pkg/protocols/file/file.go | 2 +- pkg/protocols/file/find.go | 4 +- pkg/protocols/file/find_test.go | 4 +- pkg/protocols/file/request.go | 24 +- pkg/protocols/file/request_test.go | 4 +- pkg/protocols/headless/engine/engine.go | 4 +- pkg/protocols/headless/engine/page.go | 4 +- pkg/protocols/headless/engine/page_actions.go | 2 +- .../headless/engine/page_actions_test.go | 8 +- pkg/protocols/headless/request.go | 10 +- pkg/protocols/http/build_request.go | 6 +- pkg/protocols/http/build_request_test.go | 8 +- pkg/protocols/http/cluster.go | 2 +- pkg/protocols/http/race/syncedreadcloser.go | 2 +- pkg/protocols/http/request.go | 6 +- pkg/protocols/http/request_annotations.go | 6 +- .../http/request_annotations_test.go | 4 +- pkg/protocols/http/request_fuzz.go | 8 +- pkg/protocols/http/request_test.go | 2 +- pkg/protocols/http/signerpool/signerpool.go | 2 +- pkg/protocols/http/utils.go | 2 +- pkg/protocols/network/request.go | 9 +- pkg/protocols/offlinehttp/find_test.go | 4 +- .../offlinehttp/read_response_test.go | 6 +- pkg/protocols/offlinehttp/request.go | 4 +- pkg/protocols/ssl/ssl.go | 2 +- pkg/protocols/utils/variables.go | 5 +- pkg/protocols/websocket/websocket.go | 4 +- pkg/reporting/dedupe/dedupe.go | 4 +- pkg/reporting/dedupe/dedupe_test.go | 4 +- pkg/reporting/exporters/es/elasticsearch.go | 4 +- pkg/reporting/exporters/markdown/markdown.go | 4 +- pkg/reporting/format/format_utils.go | 12 +- pkg/reporting/reporting.go | 6 +- pkg/reporting/trackers/gitlab/gitlab.go | 2 +- pkg/reporting/trackers/linear/linear.go | 4 +- pkg/scan/charts/charts.go | 4 +- pkg/scan/charts/echarts.go | 70 +- pkg/templates/cluster.go | 7 +- pkg/templates/compile.go | 6 +- pkg/templates/parser.go | 4 +- pkg/templates/templates.go | 6 +- pkg/testutils/fuzzplayground/db.go | 4 +- pkg/testutils/fuzzplayground/server.go | 12 +- pkg/testutils/integration.go | 6 +- pkg/tmplexec/flow/flow_executor.go | 4 +- pkg/tmplexec/flow/flow_internal.go | 2 +- pkg/utils/json/doc.go | 2 +- pkg/utils/json/json.go | 3 +- pkg/utils/json/json_fallback.go | 4 +- 147 files changed, 1203 insertions(+), 1347 deletions(-) diff --git a/cmd/docgen/docgen.go b/cmd/docgen/docgen.go index 51c2a195d..ca075a19c 100644 --- a/cmd/docgen/docgen.go +++ b/cmd/docgen/docgen.go @@ -19,7 +19,9 @@ func writeToFile(filename string, data []byte) { if err != nil { log.Fatalf("Could not create file %s: %s\n", filename, err) } - defer file.Close() + defer func() { + _ = file.Close() + }() _, err = file.Write(data) if err != nil { diff --git a/cmd/functional-test/main.go b/cmd/functional-test/main.go index 78114fdb3..9e605522f 100644 --- a/cmd/functional-test/main.go +++ b/cmd/functional-test/main.go @@ -41,7 +41,9 @@ func runFunctionalTests(debug bool) (error, bool) { if err != nil { return errors.Wrap(err, "could not open test cases"), true } - defer file.Close() + defer func() { + _ = file.Close() + }() errored, failedTestCases := runTestCases(file, debug) diff --git a/cmd/generate-checksum/main.go b/cmd/generate-checksum/main.go index a381387fa..9a3e7b8ed 100644 --- a/cmd/generate-checksum/main.go +++ b/cmd/generate-checksum/main.go @@ -23,7 +23,9 @@ func main() { if err != nil { log.Fatalf("Could not create file: %s\n", err) } - defer file.Close() + defer func() { + _ = file.Close() + }() err = filepath.WalkDir(templatesDirectory, func(path string, d fs.DirEntry, err error) error { if err != nil || d.IsDir() { diff --git a/cmd/integration-test/custom-dir.go b/cmd/integration-test/custom-dir.go index 550027f06..b1ea83cc6 100644 --- a/cmd/integration-test/custom-dir.go +++ b/cmd/integration-test/custom-dir.go @@ -18,7 +18,9 @@ func (h *customConfigDirTest) Execute(filePath string) error { if err != nil { return err } - defer os.RemoveAll(customTempDirectory) + defer func() { + _ = os.RemoveAll(customTempDirectory) + }() results, err := testutils.RunNucleiBareArgsAndGetResults(debug, []string{"NUCLEI_CONFIG_DIR=" + customTempDirectory}, "-t", filePath, "-u", "8x8exch02.8x8.com") if err != nil { return err diff --git a/cmd/integration-test/dsl.go b/cmd/integration-test/dsl.go index 4e4a275ef..c311b8292 100644 --- a/cmd/integration-test/dsl.go +++ b/cmd/integration-test/dsl.go @@ -21,7 +21,7 @@ type dslVersionWarning struct{} func (d *dslVersionWarning) Execute(templatePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "DSL version parsing warning test") + _, _ = fmt.Fprintf(w, "DSL version parsing warning test") }) ts := httptest.NewServer(router) defer ts.Close() @@ -37,7 +37,7 @@ type dslShowVersionWarning struct{} func (d *dslShowVersionWarning) Execute(templatePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "DSL version parsing warning test") + _, _ = fmt.Fprintf(w, "DSL version parsing warning test") }) ts := httptest.NewServer(router) defer ts.Close() diff --git a/cmd/integration-test/flow.go b/cmd/integration-test/flow.go index 46ae7cf5f..1c103b95a 100644 --- a/cmd/integration-test/flow.go +++ b/cmd/integration-test/flow.go @@ -49,7 +49,7 @@ func (t *iterateValuesFlow) Execute(filePath string) error { } router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(fmt.Sprint(testemails))) + _, _ = fmt.Fprint(w, testemails) }) router.GET("/user/"+getBase64(testemails[0]), func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.WriteHeader(http.StatusOK) diff --git a/cmd/integration-test/fuzz.go b/cmd/integration-test/fuzz.go index 230fff031..c2c4bee3a 100644 --- a/cmd/integration-test/fuzz.go +++ b/cmd/integration-test/fuzz.go @@ -55,7 +55,7 @@ func (h *httpFuzzQuery) Execute(filePath string) error { router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Header().Set("Content-Type", "text/html") value := r.URL.Query().Get("id") - fmt.Fprintf(w, "This is test matcher text: %v", value) + _, _ = fmt.Fprintf(w, "This is test matcher text: %v", value) }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -75,7 +75,7 @@ func (h *fuzzModeOverride) Execute(filePath string) error { router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Header().Set("Content-Type", "text/html") value := r.URL.Query().Get("id") - fmt.Fprintf(w, "This is test matcher text: %v", value) + _, _ = fmt.Fprintf(w, "This is test matcher text: %v", value) }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -120,7 +120,7 @@ func (h *fuzzTypeOverride) Execute(filePath string) error { router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Header().Set("Content-Type", "text/html") value := r.URL.Query().Get("id") - fmt.Fprintf(w, "This is test matcher text: %v", value) + _, _ = fmt.Fprintf(w, "This is test matcher text: %v", value) }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -164,7 +164,7 @@ func (h *HeadlessFuzzingQuery) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { resp := fmt.Sprintf("%s", r.URL.Query().Get("url")) - fmt.Fprint(w, resp) + _, _ = fmt.Fprint(w, resp) }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -190,7 +190,7 @@ func (h *fuzzMultipleMode) Execute(filePath string) error { } w.Header().Set("Content-Type", "text/html") resp := fmt.Sprintf("

This is multi-mode fuzzing test: %v

", xClientId) - fmt.Fprint(w, resp) + _, _ = fmt.Fprint(w, resp) }) ts := httptest.NewTLSServer(router) defer ts.Close() diff --git a/cmd/integration-test/generic.go b/cmd/integration-test/generic.go index 95ab5694c..f5edfc946 100644 --- a/cmd/integration-test/generic.go +++ b/cmd/integration-test/generic.go @@ -82,14 +82,15 @@ func (h *clientCertificate) Execute(filePath string) error { return } - fmt.Fprintf(w, "Hello, %s!\n", r.TLS.PeerCertificates[0].Subject) + _, _ = fmt.Fprintf(w, "Hello, %s!\n", r.TLS.PeerCertificates[0].Subject) }) _ = os.WriteFile("server.crt", []byte(serverCRT), permissionutil.ConfigFilePermission) _ = os.WriteFile("server.key", []byte(serverKey), permissionutil.ConfigFilePermission) - defer os.Remove("server.crt") - defer os.Remove("server.key") - + defer func() { + _ = os.Remove("server.crt") + _ = os.Remove("server.key") + }() serverCert, _ := tls.LoadX509KeyPair("server.crt", "server.key") certPool := x509.NewCertPool() diff --git a/cmd/integration-test/headless.go b/cmd/integration-test/headless.go index abe93acc9..04ccd295d 100644 --- a/cmd/integration-test/headless.go +++ b/cmd/integration-test/headless.go @@ -178,7 +178,9 @@ func (h *headlessFileUpload) Execute(filePath string) error { return } - defer file.Close() + defer func() { + _ = file.Close() + }() content, err := io.ReadAll(file) if err != nil { @@ -235,7 +237,9 @@ func (h *headlessFileUploadNegative) Execute(filePath string) error { return } - defer file.Close() + defer func() { + _ = file.Close() + }() content, err := io.ReadAll(file) if err != nil { diff --git a/cmd/integration-test/http.go b/cmd/integration-test/http.go index f0e5d1ae2..315f90218 100644 --- a/cmd/integration-test/http.go +++ b/cmd/integration-test/http.go @@ -108,7 +108,7 @@ func (h *httpMatcherExtractorDynamicExtractor) Execute(filePath string) error { Domains ` - fmt.Fprint(w, html) + _, _ = fmt.Fprint(w, html) }) router.GET("/domains", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { html := ` @@ -121,7 +121,7 @@ func (h *httpMatcherExtractorDynamicExtractor) Execute(filePath string) error { ` - fmt.Fprint(w, html) + _, _ = fmt.Fprint(w, html) }) ts := httptest.NewServer(router) defer ts.Close() @@ -143,7 +143,7 @@ func (h *httpInteractshRequest) Execute(filePath string) error { value := r.Header.Get("url") if value != "" { if resp, _ := retryablehttp.DefaultClient().Get(value); resp != nil { - resp.Body.Close() + _ = resp.Body.Close() } } }) @@ -213,7 +213,7 @@ func (h *httpInteractshStopAtFirstMatchRequest) Execute(filePath string) error { value := r.Header.Get("url") if value != "" { if resp, _ := retryablehttp.DefaultClient().Get(value); resp != nil { - resp.Body.Close() + _ = resp.Body.Close() } } }) @@ -235,7 +235,7 @@ func (h *httpGetHeaders) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { if strings.EqualFold(r.Header.Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test headers matcher text") + _, _ = fmt.Fprintf(w, "This is test headers matcher text") } }) ts := httptest.NewServer(router) @@ -256,7 +256,7 @@ func (h *httpGetQueryString) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { if strings.EqualFold(r.URL.Query().Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test querystring matcher text") + _, _ = fmt.Fprintf(w, "This is test querystring matcher text") } }) ts := httptest.NewServer(router) @@ -279,7 +279,7 @@ func (h *httpGetRedirects) Execute(filePath string) error { http.Redirect(w, r, "/redirected", http.StatusFound) }) router.GET("/redirected", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test redirects matcher text") + _, _ = fmt.Fprintf(w, "This is test redirects matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -329,7 +329,7 @@ func (h *httpDisableRedirects) Execute(filePath string) error { http.Redirect(w, r, "/redirected", http.StatusMovedPermanently) }) router.GET("/redirected", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test redirects matcher text") + _, _ = fmt.Fprintf(w, "This is test redirects matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -348,7 +348,7 @@ type httpGet struct{} func (h *httpGet) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -367,7 +367,7 @@ type httpDSLVariable struct{} func (h *httpDSLVariable) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -450,7 +450,7 @@ func (h *httpPostBody) Execute(filePath string) error { return } if strings.EqualFold(r.Form.Get("username"), "test") && strings.EqualFold(r.Form.Get("password"), "nuclei") { - fmt.Fprintf(w, "This is test post-body matcher text") + _, _ = fmt.Fprintf(w, "This is test post-body matcher text") } }) ts := httptest.NewServer(router) @@ -485,7 +485,7 @@ func (h *httpPostJSONBody) Execute(filePath string) error { return } if strings.EqualFold(obj.Username, "test") && strings.EqualFold(obj.Password, "nuclei") { - fmt.Fprintf(w, "This is test post-json-body matcher text") + _, _ = fmt.Fprintf(w, "This is test post-json-body matcher text") } }) ts := httptest.NewServer(router) @@ -525,7 +525,7 @@ func (h *httpPostMultipartBody) Execute(filePath string) error { return } if strings.EqualFold(password[0], "nuclei") && strings.EqualFold(file[0].Filename, "username") { - fmt.Fprintf(w, "This is test post-multipart matcher text") + _, _ = fmt.Fprintf(w, "This is test post-multipart matcher text") } }) ts := httptest.NewServer(router) @@ -555,12 +555,12 @@ func (h *httpRawDynamicExtractor) Execute(filePath string) error { return } if strings.EqualFold(r.Form.Get("testing"), "parameter") { - fmt.Fprintf(w, "Token: 'nuclei'") + _, _ = fmt.Fprintf(w, "Token: 'nuclei'") } }) router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { if strings.EqualFold(r.URL.Query().Get("username"), "nuclei") { - fmt.Fprintf(w, "Test is test-dynamic-extractor-raw matcher text") + _, _ = fmt.Fprintf(w, "Test is test-dynamic-extractor-raw matcher text") } }) ts := httptest.NewServer(router) @@ -584,7 +584,7 @@ func (h *httpRawGetQuery) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { if strings.EqualFold(r.URL.Query().Get("test"), "nuclei") { - fmt.Fprintf(w, "Test is test raw-get-query-matcher text") + _, _ = fmt.Fprintf(w, "Test is test raw-get-query-matcher text") } }) ts := httptest.NewServer(router) @@ -604,7 +604,7 @@ type httpRawGet struct{} func (h *httpRawGet) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "Test is test raw-get-matcher text") + _, _ = fmt.Fprintf(w, "Test is test raw-get-matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -633,7 +633,7 @@ func (h *httpRawWithParams) Execute(filePath string) error { if !reflect.DeepEqual(params["key2"], []string{"value2"}) { errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value2"}, params["key2"]) } - fmt.Fprintf(w, "Test is test raw-params-matcher text") + _, _ = fmt.Fprintf(w, "Test is test raw-params-matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -685,11 +685,11 @@ func (h *httpRawPayload) Execute(filePath string) error { routerErr = err return } - if !(strings.EqualFold(r.Header.Get("another_header"), "bnVjbGVp") || strings.EqualFold(r.Header.Get("another_header"), "Z3Vlc3Q=")) { + if !strings.EqualFold(r.Header.Get("another_header"), "bnVjbGVp") && !strings.EqualFold(r.Header.Get("another_header"), "Z3Vlc3Q=") { return } if strings.EqualFold(r.Form.Get("username"), "test") && (strings.EqualFold(r.Form.Get("password"), "nuclei") || strings.EqualFold(r.Form.Get("password"), "guest")) { - fmt.Fprintf(w, "Test is raw-payload matcher text") + _, _ = fmt.Fprintf(w, "Test is raw-payload matcher text") } }) ts := httptest.NewServer(router) @@ -719,7 +719,7 @@ func (h *httpRawPostBody) Execute(filePath string) error { return } if strings.EqualFold(r.Form.Get("username"), "test") && strings.EqualFold(r.Form.Get("password"), "nuclei") { - fmt.Fprintf(w, "Test is test raw-post-body-matcher text") + _, _ = fmt.Fprintf(w, "Test is test raw-post-body-matcher text") } }) ts := httptest.NewServer(router) @@ -869,7 +869,7 @@ func (h *httpRawCookieReuse) Execute(filePath string) error { } if strings.EqualFold(cookie.Value, "test") { - fmt.Fprintf(w, "Test is test-cookie-reuse matcher text") + _, _ = fmt.Fprintf(w, "Test is test-cookie-reuse matcher text") } }) ts := httptest.NewServer(router) @@ -947,7 +947,9 @@ func (h *httpRequestSelfContained) Execute(filePath string) error { go func() { _ = server.ListenAndServe() }() - defer server.Close() + defer func() { + _ = server.Close() + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc") if err != nil { @@ -983,7 +985,9 @@ func (h *httpRequestSelfContainedWithParams) Execute(filePath string) error { go func() { _ = server.ListenAndServe() }() - defer server.Close() + defer func() { + _ = server.Close() + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc") if err != nil { @@ -1016,7 +1020,9 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error { go func() { _ = server.ListenAndServe() }() - defer server.Close() + defer func() { + _ = server.Close() + }() // create temp file FileLoc, err := os.CreateTemp("", "self-contained-payload-*.txt") @@ -1026,7 +1032,9 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error { if _, err := FileLoc.Write([]byte("one\ntwo\n")); err != nil { return errorutil.NewWithErr(err).Msgf("failed to write payload to temp file") } - defer FileLoc.Close() + defer func() { + _ = FileLoc.Close() + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name(), "-esc") if err != nil { @@ -1049,7 +1057,7 @@ type httpGetCaseInsensitive struct{} func (h *httpGetCaseInsensitive) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "THIS IS TEST MATCHER TEXT") + _, _ = fmt.Fprintf(w, "THIS IS TEST MATCHER TEXT") }) ts := httptest.NewServer(router) defer ts.Close() @@ -1068,7 +1076,7 @@ type httpGetCaseInsensitiveCluster struct{} func (h *httpGetCaseInsensitiveCluster) Execute(filesPath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -1151,7 +1159,7 @@ type httpStopAtFirstMatch struct{} func (h *httpStopAtFirstMatch) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test") + _, _ = fmt.Fprintf(w, "This is test") }) ts := httptest.NewServer(router) defer ts.Close() @@ -1170,7 +1178,7 @@ type httpStopAtFirstMatchWithExtractors struct{} func (h *httpStopAtFirstMatchWithExtractors) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test") + _, _ = fmt.Fprintf(w, "This is test") }) ts := httptest.NewServer(router) defer ts.Close() @@ -1189,7 +1197,7 @@ type httpVariables struct{} func (h *httpVariables) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "%s\n%s\n%s", r.Header.Get("Test"), r.Header.Get("Another"), r.Header.Get("Email")) + _, _ = fmt.Fprintf(w, "%s\n%s\n%s", r.Header.Get("Test"), r.Header.Get("Another"), r.Header.Get("Email")) }) ts := httptest.NewServer(router) defer ts.Close() @@ -1291,7 +1299,7 @@ func (h *httpRedirectMatchURL) Execute(filePath string) error { _, _ = w.Write([]byte("This is test redirects matcher text")) }) router.GET("/redirected", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test redirects matcher text") + _, _ = fmt.Fprintf(w, "This is test redirects matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -1339,7 +1347,7 @@ func (h *annotationTimeout) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { time.Sleep(4 * time.Second) - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -1359,7 +1367,7 @@ func (h *customAttackType) Execute(filePath string) error { got := []string{} router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { got = append(got, r.URL.RawQuery) - fmt.Fprintf(w, "This is test custom payload") + _, _ = fmt.Fprintf(w, "This is test custom payload") }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -1407,7 +1415,7 @@ func (h *httpCLBodyWithoutHeader) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Header()["Content-Length"] = []string{"-1"} - fmt.Fprintf(w, "this is a test") + _, _ = fmt.Fprintf(w, "this is a test") }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -1427,7 +1435,7 @@ func (h *httpCLBodyWithHeader) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Header()["Content-Length"] = []string{"50000"} - fmt.Fprintf(w, "this is a test") + _, _ = fmt.Fprintf(w, "this is a test") }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -1446,7 +1454,7 @@ type ConstantWithCliVar struct{} func (h *ConstantWithCliVar) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprint(w, r.URL.Query().Get("p")) + _, _ = fmt.Fprint(w, r.URL.Query().Get("p")) }) ts := httptest.NewTLSServer(router) defer ts.Close() @@ -1483,10 +1491,10 @@ type httpDisablePathAutomerge struct{} func (h *httpDisablePathAutomerge) Execute(filePath string) error { router := httprouter.New() router.GET("/api/v1/test", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprint(w, r.URL.Query().Get("id")) + _, _ = fmt.Fprint(w, r.URL.Query().Get("id")) }) router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprint(w, "empty path in raw request") + _, _ = fmt.Fprint(w, "empty path in raw request") }) ts := httptest.NewServer(router) @@ -1520,10 +1528,10 @@ func (h *httpPreprocessor) Execute(filePath string) error { value := r.URL.RequestURI() if re.MatchString(value) { w.WriteHeader(http.StatusOK) - fmt.Fprint(w, "ok") + _, _ = fmt.Fprint(w, "ok") } else { w.WriteHeader(http.StatusBadRequest) - fmt.Fprint(w, "not ok") + _, _ = fmt.Fprint(w, "not ok") } }) ts := httptest.NewServer(router) @@ -1544,11 +1552,11 @@ func (h *httpMultiRequest) Execute(filePath string) error { router := httprouter.New() router.GET("/ping", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.WriteHeader(http.StatusOK) - fmt.Fprint(w, "ping") + _, _ = fmt.Fprint(w, "ping") }) router.GET("/pong", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.WriteHeader(http.StatusOK) - fmt.Fprint(w, "pong") + _, _ = fmt.Fprint(w, "pong") }) ts := httptest.NewServer(router) defer ts.Close() diff --git a/cmd/integration-test/integration-test.go b/cmd/integration-test/integration-test.go index a35d7f92a..160dd13e1 100644 --- a/cmd/integration-test/integration-test.go +++ b/cmd/integration-test/integration-test.go @@ -89,7 +89,9 @@ func main() { // start fuzz playground server defer fuzzplayground.Cleanup() server := fuzzplayground.GetPlaygroundServer() - defer server.Close() + defer func() { + _ = server.Close() + }() go func() { if err := server.Start("localhost:8082"); err != nil { if !strings.Contains(err.Error(), "Server closed") { diff --git a/cmd/integration-test/library.go b/cmd/integration-test/library.go index 1324688e0..22f7f4ac0 100644 --- a/cmd/integration-test/library.go +++ b/cmd/integration-test/library.go @@ -48,9 +48,9 @@ func (h *goIntegrationTest) Execute(templatePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") if strings.EqualFold(r.Header.Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test headers matcher text") + _, _ = fmt.Fprintf(w, "This is test headers matcher text") } }) ts := httptest.NewServer(router) diff --git a/cmd/integration-test/loader.go b/cmd/integration-test/loader.go index 8e5ea40ff..d1114ef33 100644 --- a/cmd/integration-test/loader.go +++ b/cmd/integration-test/loader.go @@ -31,9 +31,9 @@ func (h *remoteTemplateList) Execute(templateList string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") if strings.EqualFold(r.Header.Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test headers matcher text") + _, _ = fmt.Fprintf(w, "This is test headers matcher text") } }) @@ -55,7 +55,9 @@ func (h *remoteTemplateList) Execute(templateList string) error { if err != nil { return err } - defer os.Remove("test-config.yaml") + defer func() { + _ = os.Remove("test-config.yaml") + }() results, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/template_list", "-config", "test-config.yaml") if err != nil { @@ -72,9 +74,9 @@ func (h *excludedTemplate) Execute(templateList string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") if strings.EqualFold(r.Header.Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test headers matcher text") + _, _ = fmt.Fprintf(w, "This is test headers matcher text") } }) ts := httptest.NewServer(router) @@ -95,9 +97,9 @@ func (h *remoteTemplateListNotAllowed) Execute(templateList string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") if strings.EqualFold(r.Header.Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test headers matcher text") + _, _ = fmt.Fprintf(w, "This is test headers matcher text") } }) @@ -130,9 +132,9 @@ func (h *remoteWorkflowList) Execute(workflowList string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") if strings.EqualFold(r.Header.Get("test"), "nuclei") { - fmt.Fprintf(w, "This is test headers matcher text") + _, _ = fmt.Fprintf(w, "This is test headers matcher text") } }) @@ -154,7 +156,9 @@ func (h *remoteWorkflowList) Execute(workflowList string) error { if err != nil { return err } - defer os.Remove("test-config.yaml") + defer func() { + _ = os.Remove("test-config.yaml") + }() results, err := testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/workflow_list", "-config", "test-config.yaml") if err != nil { @@ -177,7 +181,9 @@ func (h *nonExistentTemplateList) Execute(nonExistingTemplateList string) error if err != nil { return err } - defer os.Remove("test-config.yaml") + defer func() { + _ = os.Remove("test-config.yaml") + }() _, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-template-url", ts.URL+"/404", "-config", "test-config.yaml") if err == nil { @@ -200,7 +206,9 @@ func (h *nonExistentWorkflowList) Execute(nonExistingWorkflowList string) error if err != nil { return err } - defer os.Remove("test-config.yaml") + defer func() { + _ = os.Remove("test-config.yaml") + }() _, err = testutils.RunNucleiBareArgsAndGetResults(debug, nil, "-target", ts.URL, "-workflow-url", ts.URL+"/404", "-config", "test-config.yaml") if err == nil { diff --git a/cmd/integration-test/network.go b/cmd/integration-test/network.go index 2e0ff0f26..1fb1fe709 100644 --- a/cmd/integration-test/network.go +++ b/cmd/integration-test/network.go @@ -33,7 +33,9 @@ func (h *networkBasic) Execute(filePath string) error { var routerErr error ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { @@ -50,11 +52,11 @@ func (h *networkBasic) Execute(filePath string) error { results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug) if err != nil { - fmt.Fprintf(os.Stderr, "Could not run nuclei: %s\n", err) + _, _ = fmt.Fprintf(os.Stderr, "Could not run nuclei: %s\n", err) return err } if routerErr != nil { - fmt.Fprintf(os.Stderr, "routerErr: %s\n", routerErr) + _, _ = fmt.Fprintf(os.Stderr, "routerErr: %s\n", routerErr) return routerErr } @@ -68,7 +70,9 @@ func (h *networkMultiStep) Execute(filePath string) error { var routerErr error ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 5, time.Duration(5)*time.Second) if err != nil { @@ -114,7 +118,9 @@ type networkRequestSelContained struct{} // Execute executes a test case and returns an error if occurred func (h *networkRequestSelContained) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() _, _ = conn.Write([]byte("Authentication successful")) }) @@ -134,7 +140,9 @@ func (h *networkVariables) Execute(filePath string) error { var routerErr error ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { @@ -162,7 +170,9 @@ type networkPort struct{} func (n *networkPort) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, 23846, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { @@ -195,7 +205,9 @@ func (n *networkPort) Execute(filePath string) error { // this is positive test case where we expect port to be overridden and 34567 to be used ts2 := testutils.NewTCPServer(nil, 34567, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { diff --git a/cmd/integration-test/ssl.go b/cmd/integration-test/ssl.go index de7a91a94..c824dec68 100644 --- a/cmd/integration-test/ssl.go +++ b/cmd/integration-test/ssl.go @@ -21,7 +21,9 @@ type sslBasic struct{} // Execute executes a test case and returns an error if occurred func (h *sslBasic) Execute(filePath string) error { ts := testutils.NewTCPServer(&tls.Config{}, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data := make([]byte, 4) if _, err := conn.Read(data); err != nil { return @@ -42,7 +44,9 @@ type sslBasicZtls struct{} // Execute executes a test case and returns an error if occurred func (h *sslBasicZtls) Execute(filePath string) error { ts := testutils.NewTCPServer(&tls.Config{}, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data := make([]byte, 4) if _, err := conn.Read(data); err != nil { return @@ -63,7 +67,9 @@ type sslCustomCipher struct{} // Execute executes a test case and returns an error if occurred func (h *sslCustomCipher) Execute(filePath string) error { ts := testutils.NewTCPServer(&tls.Config{CipherSuites: []uint16{tls.TLS_AES_128_GCM_SHA256}}, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data := make([]byte, 4) if _, err := conn.Read(data); err != nil { return @@ -84,7 +90,9 @@ type sslCustomVersion struct{} // Execute executes a test case and returns an error if occurred func (h *sslCustomVersion) Execute(filePath string) error { ts := testutils.NewTCPServer(&tls.Config{MinVersion: tls.VersionTLS12, MaxVersion: tls.VersionTLS12}, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data := make([]byte, 4) if _, err := conn.Read(data); err != nil { return @@ -104,7 +112,9 @@ type sslWithVars struct{} func (h *sslWithVars) Execute(filePath string) error { ts := testutils.NewTCPServer(&tls.Config{}, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data := make([]byte, 4) if _, err := conn.Read(data); err != nil { return @@ -128,7 +138,9 @@ func (h *sslMultiReq) Execute(filePath string) error { MinVersion: tls.VersionSSL30, MaxVersion: tls.VersionTLS11, }, defaultStaticPort, func(conn net.Conn) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() data := make([]byte, 4) if _, err := conn.Read(data); err != nil { return diff --git a/cmd/integration-test/template-dir.go b/cmd/integration-test/template-dir.go index 2c60cc60c..20691da04 100644 --- a/cmd/integration-test/template-dir.go +++ b/cmd/integration-test/template-dir.go @@ -19,7 +19,9 @@ func (h *templateDirWithTargetTest) Execute(filePath string) error { if err != nil { return errorutil.NewWithErr(err).Msgf("failed to create temp dir") } - defer os.RemoveAll(tempdir) + defer func() { + _ = os.RemoveAll(tempdir) + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "8x8exch02.8x8.com", debug, "-ud", tempdir) if err != nil { diff --git a/cmd/integration-test/workflow.go b/cmd/integration-test/workflow.go index 442e5169f..3032e8b59 100644 --- a/cmd/integration-test/workflow.go +++ b/cmd/integration-test/workflow.go @@ -62,7 +62,7 @@ type workflowBasic struct{} func (h *workflowBasic) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -81,7 +81,7 @@ type workflowConditionMatched struct{} func (h *workflowConditionMatched) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -100,7 +100,7 @@ type workflowConditionUnmatch struct{} func (h *workflowConditionUnmatch) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -119,7 +119,7 @@ type workflowMatcherName struct{} func (h *workflowMatcherName) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -138,7 +138,7 @@ type workflowComplexConditions struct{} func (h *workflowComplexConditions) Execute(filePath string) error { router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) ts := httptest.NewServer(router) defer ts.Close() @@ -162,11 +162,11 @@ type workflowHttpKeyValueShare struct{} func (h *workflowHttpKeyValueShare) Execute(filePath string) error { router := httprouter.New() router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "href=\"test-value\"") + _, _ = fmt.Fprintf(w, "href=\"test-value\"") }) router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { body, _ := io.ReadAll(r.Body) - fmt.Fprintf(w, "%s", body) + _, _ = fmt.Fprintf(w, "%s", body) }) ts := httptest.NewServer(router) defer ts.Close() @@ -214,11 +214,11 @@ func (h *workflowMultiProtocolKeyValueShare) Execute(filePath string) error { router := httprouter.New() // the response of path1 contains a domain that will be extracted and shared with the second template router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "href=\"blog.projectdiscovery.io\"") + _, _ = fmt.Fprintf(w, "href=\"blog.projectdiscovery.io\"") }) // path2 responds with the value of the "extracted" query parameter, e.g.: /path2?extracted=blog.projectdiscovery.io => blog.projectdiscovery.io router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "%s", r.URL.Query().Get("extracted")) + _, _ = fmt.Fprintf(w, "%s", r.URL.Query().Get("extracted")) }) ts := httptest.NewServer(router) defer ts.Close() @@ -238,15 +238,15 @@ func (h *workflowMultiMatchKeyValueShare) Execute(filePath string) error { var receivedData []string router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "This is test matcher text") + _, _ = fmt.Fprintf(w, "This is test matcher text") }) router.GET("/path1", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - fmt.Fprintf(w, "href=\"test-value-%s\"", r.URL.Query().Get("v")) + _, _ = fmt.Fprintf(w, "href=\"test-value-%s\"", r.URL.Query().Get("v")) }) router.GET("/path2", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { body, _ := io.ReadAll(r.Body) receivedData = append(receivedData, string(body)) - fmt.Fprintf(w, "test-value") + _, _ = fmt.Fprintf(w, "test-value") }) ts := httptest.NewServer(router) defer ts.Close() diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 8cc2b53f1..2fe3694e6 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -140,8 +140,8 @@ func main() { } pprof.StopCPUProfile() - memProfileFile.Close() - traceFile.Close() + _ = memProfileFile.Close() + _ = traceFile.Close() trace.Stop() runtime.MemProfileRate = oldMemProfileRate @@ -227,7 +227,7 @@ func main() { nucleiRunner.Close() // on successful execution remove the resume file in case it exists if fileutil.FileExists(resumeFileName) { - os.Remove(resumeFileName) + _ = os.Remove(resumeFileName) } } diff --git a/cmd/nuclei/main_benchmark_test.go b/cmd/nuclei/main_benchmark_test.go index baf9dbfab..f8504f8cc 100644 --- a/cmd/nuclei/main_benchmark_test.go +++ b/cmd/nuclei/main_benchmark_test.go @@ -22,7 +22,7 @@ func TestMain(m *testing.M) { // Set up gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) - os.Setenv("DISABLE_STDOUT", "true") + _ = os.Setenv("DISABLE_STDOUT", "true") var err error @@ -44,7 +44,7 @@ func TestMain(m *testing.M) { dummyServer.Close() _ = os.RemoveAll(projectPath) - os.Unsetenv("DISABLE_STDOUT") + _ = os.Unsetenv("DISABLE_STDOUT") os.Exit(exitCode) } diff --git a/cmd/tmc/main.go b/cmd/tmc/main.go index 521929c75..aad80dd32 100644 --- a/cmd/tmc/main.go +++ b/cmd/tmc/main.go @@ -135,7 +135,9 @@ func process(opts options) error { if err != nil { return err } - defer os.RemoveAll(tempDir) + defer func() { + _ = os.RemoveAll(tempDir) + }() var errFile *os.File if opts.errorLogFile != "" { @@ -143,7 +145,9 @@ func process(opts options) error { if err != nil { gologger.Fatal().Msgf("could not open error log file: %s\n", err) } - defer errFile.Close() + defer func() { + _ = errFile.Close() + }() } templateCatalog := disk.NewCatalog(filepath.Dir(opts.input)) @@ -226,7 +230,7 @@ func logErrMsg(path string, err error, debug bool, errFile *os.File) string { msg = fmt.Sprintf("❌ template: %s err: %s\n", path, err) } if errFile != nil { - _, _ = errFile.WriteString(fmt.Sprintf("❌ template: %s err: %s\n", path, err)) + _, _ = fmt.Fprintf(errFile, "❌ template: %s err: %s\n", path, err) } return msg } diff --git a/cmd/tools/fuzzplayground/main.go b/cmd/tools/fuzzplayground/main.go index 0ab764e8b..b65d99ed2 100644 --- a/cmd/tools/fuzzplayground/main.go +++ b/cmd/tools/fuzzplayground/main.go @@ -18,7 +18,9 @@ func main() { defer fuzzplayground.Cleanup() server := fuzzplayground.GetPlaygroundServer() - defer server.Close() + defer func() { + _ = server.Close() + }() // Start the server if err := server.Start(addr); err != nil { diff --git a/examples/with_speed_control/main.go b/examples/with_speed_control/main.go index b56df967c..48fb94d88 100644 --- a/examples/with_speed_control/main.go +++ b/examples/with_speed_control/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "log" "sync" "time" @@ -34,7 +35,7 @@ func main() { } func initializeNucleiEngine() (*nuclei.NucleiEngine, error) { - return nuclei.NewNucleiEngine( + return nuclei.NewNucleiEngineCtx(context.TODO(), nuclei.WithTemplateFilters(nuclei.TemplateFilters{Tags: []string{"oast"}}), nuclei.EnableStatsWithOpts(nuclei.StatsOptions{MetricServerPort: 6064}), nuclei.WithGlobalRateLimit(1, time.Second), diff --git a/go.mod b/go.mod index 23ff55738..f2913c875 100644 --- a/go.mod +++ b/go.mod @@ -1,93 +1,97 @@ module github.com/projectdiscovery/nuclei/v3 -go 1.23.0 - -toolchain go1.24.1 +go 1.24.1 require ( github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible github.com/andygrunwald/go-jira v1.16.0 - github.com/antchfx/htmlquery v1.3.0 + github.com/antchfx/htmlquery v1.3.4 github.com/bluele/gcache v0.0.2 - github.com/go-playground/validator/v10 v10.14.1 + github.com/go-playground/validator/v10 v10.26.0 github.com/go-rod/rod v0.116.2 - github.com/gobwas/ws v1.2.1 + github.com/gobwas/ws v1.4.0 github.com/google/go-github v17.0.0+incompatible - github.com/invopop/jsonschema v0.12.0 - github.com/itchyny/gojq v0.12.13 + github.com/invopop/jsonschema v0.13.0 + github.com/itchyny/gojq v0.12.17 github.com/json-iterator/go v1.1.12 github.com/julienschmidt/httprouter v1.3.0 github.com/logrusorgru/aurora v2.0.3+incompatible - github.com/miekg/dns v1.1.62 + github.com/miekg/dns v1.1.66 github.com/olekukonko/tablewriter v0.0.5 github.com/pkg/errors v0.9.1 github.com/projectdiscovery/clistats v0.1.1 - github.com/projectdiscovery/fastdialer v0.4.0 - github.com/projectdiscovery/hmap v0.0.88 + 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.99 - github.com/projectdiscovery/retryablehttp-go v1.0.111 + github.com/projectdiscovery/retryabledns v1.0.103 + github.com/projectdiscovery/retryablehttp-go v1.0.116 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.0 github.com/segmentio/ksuid v1.0.4 - github.com/shirou/gopsutil/v3 v3.24.2 // indirect + github.com/shirou/gopsutil/v3 v3.24.5 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/cast v1.5.1 + 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.2 - github.com/xanzy/go-gitlab v0.107.0 + github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b go.uber.org/multierr v1.11.0 - golang.org/x/net v0.39.0 - golang.org/x/oauth2 v0.22.0 - golang.org/x/text v0.24.0 + golang.org/x/net v0.41.0 + golang.org/x/oauth2 v0.30.0 + golang.org/x/text v0.26.0 gopkg.in/yaml.v2 v2.4.0 ) require ( - code.gitea.io/sdk/gitea v0.17.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 - github.com/DataDog/gostackparse v0.6.0 - github.com/Masterminds/semver/v3 v3.2.1 + code.gitea.io/sdk/gitea v0.21.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 + github.com/DataDog/gostackparse v0.7.0 + github.com/Masterminds/semver/v3 v3.4.0 github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 + github.com/alecthomas/chroma v0.10.0 github.com/alitto/pond v1.9.2 - github.com/antchfx/xmlquery v1.3.17 + github.com/antchfx/xmlquery v1.4.4 + github.com/antchfx/xpath v1.3.4 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 - github.com/aws/aws-sdk-go-v2 v1.19.0 - github.com/aws/aws-sdk-go-v2/config v1.18.28 - github.com/aws/aws-sdk-go-v2/credentials v1.13.27 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72 - github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0 - github.com/bytedance/sonic v1.12.8 + github.com/aws/aws-sdk-go-v2 v1.36.5 + github.com/aws/aws-sdk-go-v2/config v1.29.17 + github.com/aws/aws-sdk-go-v2/credentials v1.17.70 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82 + github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 + github.com/bytedance/sonic v1.13.3 github.com/cespare/xxhash v1.1.0 - github.com/charmbracelet/glamour v0.8.0 + github.com/charmbracelet/glamour v0.10.0 github.com/clbanning/mxj/v2 v2.7.0 github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c github.com/docker/go-units v0.5.0 - github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 + github.com/dop251/goja v0.0.0-20250624190929-4d26883d182a + github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 github.com/fatih/structs v1.1.0 - github.com/getkin/kin-openapi v0.126.0 - github.com/go-git/go-git/v5 v5.13.0 - github.com/go-ldap/ldap/v3 v3.4.5 + github.com/getkin/kin-openapi v0.132.0 + github.com/go-echarts/go-echarts/v2 v2.6.0 + github.com/go-git/go-git/v5 v5.16.2 + github.com/go-ldap/ldap/v3 v3.4.11 github.com/go-pg/pg v8.0.7+incompatible - github.com/go-sql-driver/mysql v1.7.1 + github.com/go-sql-driver/mysql v1.9.3 github.com/goccy/go-json v0.10.5 + github.com/google/uuid v1.6.0 github.com/h2non/filetype v1.1.3 github.com/invopop/yaml v0.3.1 + github.com/jcmturner/gokrb5/v8 v8.4.4 github.com/kitabisa/go-ci v1.0.3 - github.com/labstack/echo/v4 v4.13.3 + github.com/labstack/echo/v4 v4.13.4 github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa github.com/lib/pq v1.10.9 - github.com/mattn/go-sqlite3 v1.14.22 - github.com/mholt/archives v0.1.0 - github.com/microsoft/go-mssqldb v1.6.0 - github.com/ory/dockertest/v3 v3.10.0 - github.com/praetorian-inc/fingerprintx v1.1.9 - github.com/projectdiscovery/dsl v0.4.3 + github.com/mattn/go-sqlite3 v1.14.28 + github.com/mholt/archives v0.1.3 + github.com/microsoft/go-mssqldb v1.9.2 + github.com/ory/dockertest/v3 v3.12.0 + github.com/praetorian-inc/fingerprintx v1.1.15 + github.com/projectdiscovery/dsl v0.5.0 github.com/projectdiscovery/fasttemplate v0.0.2 + github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb github.com/projectdiscovery/goflags v0.1.74 github.com/projectdiscovery/gologger v1.1.54 @@ -96,23 +100,28 @@ 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/ratelimit v0.0.80 - github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 + 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.0.10 - github.com/projectdiscovery/useragent v0.0.100 - github.com/projectdiscovery/utils v0.4.19 - github.com/projectdiscovery/wappalyzergo v0.2.28 - github.com/redis/go-redis/v9 v9.1.0 + github.com/projectdiscovery/uncover v1.1.0 + github.com/projectdiscovery/useragent v0.0.101 + github.com/projectdiscovery/utils v0.4.21 + github.com/projectdiscovery/wappalyzergo v0.2.35 + github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 github.com/stretchr/testify v1.10.0 github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 - github.com/yassinebenaid/godump v0.10.0 - github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706 - go.mongodb.org/mongo-driver v1.17.0 - golang.org/x/term v0.31.0 + github.com/trivago/tgo v1.0.7 + github.com/yassinebenaid/godump v0.11.1 + github.com/zmap/zgrab2 v0.2.0 + gitlab.com/gitlab-org/api/client-go v0.130.1 + go.mongodb.org/mongo-driver v1.17.4 + golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b + golang.org/x/term v0.32.0 + golang.org/x/tools v0.34.0 gopkg.in/yaml.v3 v3.0.1 moul.io/http2curl v1.0.0 ) @@ -120,22 +129,44 @@ require ( require ( aead.dev/minisign v0.2.0 // indirect dario.cat/mergo v1.0.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect + github.com/42wim/httpsig v1.2.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect + github.com/PuerkitoBio/goquery v1.10.3 // indirect github.com/STARRY-S/zip v0.2.1 // indirect github.com/VividCortex/ewma v1.2.0 // indirect + github.com/akrylysov/pogreb v0.10.2 // indirect github.com/alecthomas/chroma/v2 v2.14.0 // indirect - github.com/andybalholm/brotli v1.1.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.27 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.30 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.4 // indirect + github.com/alecthomas/kingpin/v2 v2.4.0 // indirect + github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect + github.com/andybalholm/cascadia v1.3.3 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect + github.com/aws/smithy-go v1.22.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/aymerick/douceur v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/bits-and-blooms/bloom/v3 v3.5.0 // indirect @@ -143,95 +174,149 @@ require ( github.com/bodgit/sevenzip v1.6.0 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect - github.com/bytedance/sonic/loader v0.2.2 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/charmbracelet/lipgloss v0.13.0 // indirect - github.com/charmbracelet/x/ansi v0.3.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/caddyserver/certmagic v0.19.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13 // indirect + github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/cheggaaa/pb/v3 v3.1.4 // indirect github.com/cloudflare/cfssl v1.6.4 // indirect - github.com/cloudflare/circl v1.3.8 // indirect + github.com/cloudflare/circl v1.6.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect - github.com/containerd/continuity v0.4.2 // indirect - github.com/cyphar/filepath-securejoin v0.2.5 // indirect + github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect + github.com/containerd/continuity v0.4.5 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/dlclark/regexp2 v1.11.4 // indirect - github.com/docker/cli v24.0.5+incompatible // indirect - github.com/docker/docker v24.0.9+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect + github.com/docker/cli v27.4.1+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 github.com/fatih/color v1.16.0 // indirect 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.2 // indirect - github.com/gaissmai/bart v0.17.10 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // 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 - github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect + github.com/gin-gonic/gin v1.9.0 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-fed/httpsig v1.1.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect + 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.2.1 // indirect + github.com/goburrow/cache v0.1.4 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.1.4 // indirect github.com/google/go-github/v30 v30.1.0 // indirect - github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect + github.com/hdm/jarm-go v0.0.7 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/itchyny/timefmt-go v0.1.6 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/gofork v1.7.6 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kataras/jwt v0.1.10 // indirect - github.com/klauspost/compress v1.17.11 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kylelemons/godebug v1.1.0 // indirect + github.com/labstack/gommon v0.4.2 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/libdns/libdns v0.2.1 // indirect github.com/logrusorgru/aurora/v4 v4.0.0 // indirect + github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mackerelio/go-osstat v0.2.4 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mholt/acmez v1.2.0 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect + github.com/mikelolasagasti/xz v1.0.1 // indirect + github.com/minio/minlz v1.0.0 // indirect github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/sys/user v0.3.0 // indirect github.com/moby/term v0.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect - github.com/nwaples/rardecode/v2 v2.0.1 // indirect + github.com/muesli/termenv v0.16.0 // indirect + github.com/nwaples/rardecode/v2 v2.1.0 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect - github.com/opencontainers/runc v1.1.14 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/runc v1.2.3 // indirect + github.com/openrdap/rdap v0.9.1 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect - github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.17 // indirect + github.com/projectdiscovery/blackrock v0.0.1 // indirect + github.com/projectdiscovery/cdncheck v1.1.15 // indirect 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.6.7 // indirect + github.com/refraction-networking/utls v1.7.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // 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 github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skeema/knownhosts v1.3.0 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect github.com/sorairolake/lzip-go v0.3.5 // indirect - github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/btree v1.7.0 // indirect github.com/tidwall/buntdb v1.3.1 // indirect github.com/tidwall/gjson v1.18.0 // indirect @@ -241,131 +326,54 @@ require ( github.com/tidwall/rtred v0.1.2 // indirect github.com/tidwall/tinyqueue v0.1.1 // indirect github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.11 // indirect + github.com/ugorji/go/codec v1.2.9 // indirect + github.com/ulikunitz/xz v0.5.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/ysmood/fetchup v0.2.3 // indirect - github.com/ysmood/got v0.40.0 // indirect - github.com/yuin/goldmark v1.7.4 // indirect - github.com/yuin/goldmark-emoji v1.0.3 // indirect - github.com/zcalusic/sysinfo v1.0.2 // indirect - github.com/zeebo/blake3 v0.2.3 // indirect - go.uber.org/goleak v1.3.0 // indirect - go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/arch v0.3.0 // indirect - golang.org/x/sync v0.13.0 // indirect - gopkg.in/djherbis/times.v1 v1.3.0 // indirect - mellium.im/sasl v0.3.1 // indirect -) - -require ( - git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect - github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect - github.com/PuerkitoBio/goquery v1.10.3 // indirect - github.com/akrylysov/pogreb v0.10.2 // indirect - github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect - github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/andybalholm/cascadia v1.3.3 // indirect - github.com/antchfx/xpath v1.2.4 - github.com/aymerick/douceur v0.2.0 // indirect - github.com/caddyserver/certmagic v0.19.2 // indirect - github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/goburrow/cache v0.1.4 // indirect - github.com/gobwas/httphead v0.1.0 // indirect - github.com/gobwas/pool v0.2.1 // indirect - github.com/golang-jwt/jwt/v4 v4.5.1 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/google/uuid v1.6.0 - github.com/gorilla/css v1.0.1 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/hdm/jarm-go v0.0.7 // indirect - github.com/itchyny/timefmt-go v0.1.5 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/leodido/go-urn v1.2.4 // indirect - github.com/libdns/libdns v0.2.1 // indirect - github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mholt/acmez v1.2.0 // indirect - github.com/microcosm-cc/bluemonday v1.0.27 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/networkpolicy v0.1.14 - github.com/rivo/uniseg v0.4.7 // indirect - github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/trivago/tgo v1.0.7 - github.com/ulikunitz/xz v0.5.12 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/ysmood/goob v0.4.0 // indirect + github.com/ysmood/got v0.40.0 // indirect github.com/ysmood/gson v0.7.3 // indirect github.com/ysmood/leakless v0.9.0 // indirect + github.com/yuin/goldmark v1.7.8 // indirect + github.com/yuin/goldmark-emoji v1.0.5 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect + github.com/zcalusic/sysinfo v1.0.2 // indirect + github.com/zeebo/blake3 v0.2.3 // indirect github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect - github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // indirect + github.com/zmap/zcrypto v0.0.0-20250324021606-4f0ea0eaccac // indirect go.etcd.io/bbolt v1.3.10 // indirect go.uber.org/zap v1.25.0 // indirect + go4.org v0.0.0-20230225012048-214862532bf5 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 - golang.org/x/mod v0.22.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.29.0 - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/mod v0.25.0 // indirect + golang.org/x/sync v0.15.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/time v0.11.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect + gopkg.in/djherbis/times.v1 v1.3.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect + mellium.im/sasl v0.3.2 // indirect ) -require ( - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v1.1.3 // indirect - github.com/alecthomas/chroma v0.10.0 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect - github.com/aws/smithy-go v1.13.5 // indirect - github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562 - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-echarts/go-echarts/v2 v2.3.3 - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.0 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jcmturner/gokrb5/v8 v8.4.4 - github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/labstack/gommon v0.4.2 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) +// experimental module replacements that subject to change +replace github.com/zmap/zcrypto v0.0.0-20250324021606-4f0ea0eaccac => github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // https://go.dev/ref/mod#go-mod-file-retract retract v3.2.0 // retract due to broken js protocol issue diff --git a/go.sum b/go.sum index 3c80d1e5d..b3d9f81f1 100644 --- a/go.sum +++ b/go.sum @@ -8,69 +8,61 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -code.gitea.io/sdk/gitea v0.17.0 h1:8JPBss4+Jf7AE1YcfyiGrngTXE8dFSG3si/bypsTH34= -code.gitea.io/sdk/gitea v0.17.0/go.mod h1:ndkDk99BnfiUCCYEUhpNzi0lpmApXlwRFqClBlOlEBg= +code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4= +code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a h1:3i+FJ7IpSZHL+VAjtpQeZCRhrpP0odl5XfoLBY4fxJ8= git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a/go.mod h1:C7hXLmFmPYPjIDGfQl1clsmQ5TMEQfmzWTrJk475bUs= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= -github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613EeLayJiRAJuKlBGy+m22qWG+WRg= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4= +github.com/42wim/httpsig v1.2.2 h1:ofAYoHUNs/MJOLqQ8hIxeyz2QxOz8qdSVvp3PX/oPgA= +github.com/42wim/httpsig v1.2.2/go.mod h1:P/UYo7ytNBFwc+dg35IubuAUIs8zj5zzFIgUCEl55WY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1 h1:Wgf5rZba3YZqeTNJPtvqZoBu1sBN/L4sry+u2U3Y75w= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1/go.mod h1:xxCBG/f/4Vbmh2XQJBsOmNdxWUY5j/s27jujKPbQf14= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/gostackparse v0.6.0 h1:egCGQviIabPwsyoWpGvIBGrEnNWez35aEO7OJ1vBI4o= -github.com/DataDog/gostackparse v0.6.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= +github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= +github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 h1:KFac3SiGbId8ub47e7kd2PLZeACxc1LkiiNoDOFRClE= github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057/go.mod h1:iLB2pivrPICvLOuROKmlqURtFIEsoJZaMidQfCG1+D4= github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 h1:ZbFL+BDfBqegi+/Ssh7im5+aQfBRx6it+kHnC7jaDU8= @@ -80,19 +72,15 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= -github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= -github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= github.com/RumbleDiscovery/rumble-tools v0.0.0-20201105153123-f2adbb3244d2/go.mod h1:jD2+mU+E2SZUuAOHZvZj4xP4frlOo+N/YrXDvASFhkE= github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg= github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/akrylysov/pogreb v0.10.2 h1:e6PxmeyEhWyi2AKOBIJzAEi4HkiC+lKyCocRGlnDi78= github.com/akrylysov/pogreb v0.10.2/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= @@ -101,87 +89,75 @@ github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbf github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I= -github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= -github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= +github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs= github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 h1:8PmGpDEZl9yDpcdEr6Odf23feCxK3LNUNMxjXg41pZQ= +github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ= github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antchfx/htmlquery v1.3.0 h1:5I5yNFOVI+egyia5F2s/5Do2nFWxJz41Tr3DyfKD25E= -github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6eXr/2SebQ8= -github.com/antchfx/xmlquery v1.3.17 h1:d0qWjPp/D+vtRw7ivCwT5ApH/3CkQU8JOeo3245PpTk= -github.com/antchfx/xmlquery v1.3.17/go.mod h1:Afkq4JIeXut75taLSuI31ISJ/zeq+3jG7TunF7noreA= -github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= -github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY= -github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1jdQ= +github.com/antchfx/htmlquery v1.3.4/go.mod h1:K9os0BwIEmLAvTqaNSua8tXLWRWZpocZIH73OzWQbwM= +github.com/antchfx/xmlquery v1.4.4 h1:mxMEkdYP3pjKSftxss4nUHfjBhnMk4imGoR96FRY2dg= +github.com/antchfx/xmlquery v1.4.4/go.mod h1:AEPEEPYE9GnA2mj5Ur2L5Q5/2PycJ0N9Fusrx9b12fc= +github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/antchfx/xpath v1.3.4 h1:1ixrW1VnXd4HurCj7qnqnR0jo14g8JMe20Fshg1Vgz4= +github.com/antchfx/xpath v1.3.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= -github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.18.28 h1:TINEaKyh1Td64tqFvn09iYpKiWjmHYrG1fa91q2gnqw= -github.com/aws/aws-sdk-go-v2/config v1.18.28/go.mod h1:nIL+4/8JdAuNHEjn/gPEXqtnS02Q3NXB/9Z7o5xE4+A= -github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILVPQ6FS5AwF/OyG1kA= -github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72 h1:m0MmP89v1B0t3b8W8rtATU76KNsodak69QtiokHyEvo= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.72/go.mod h1:ylOTxIuoTL+XjH46Omv2iPjHdeGUk3SQ4hxYho4EHMA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.27 h1:cZG7psLfqpkB6H+fIrgUDWmlzM474St1LP0jcz272yI= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.27/go.mod h1:ZdjYvJpDlefgh8/hWelJhqgqJeodxu4SmbVsSdBlL7E= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.30 h1:Bje8Xkh2OWpjBdNfXLrnn8eZg569dUQmhgtydxAYyP0= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.30/go.mod h1:qQtIBl5OVMfmeQkz8HaVyh5DzFmmFXyvK27UgIgOr4c= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.4 h1:hx4WksB0NRQ9utR+2c3gEGzl6uKj3eM6PMQ6tN3lgXs= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.4/go.mod h1:JniVpqvw90sVjNqanGLufrVapWySL28fhBlYgl96Q/w= -github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0 h1:PalLOEGZ/4XfQxpGZFTLaoJSmPoybnqJYotaIZEf/Rg= -github.com/aws/aws-sdk-go-v2/service/s3 v1.37.0/go.mod h1:PwyKKVL0cNkC37QwLcrhyeCrAk+5bY8O2ou7USyAS2A= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2OZgH1ypC114H04U= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY= -github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= +github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY= +github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= +github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70/go.mod h1:M+lWhhmomVGgtuPOhO85u4pEa3SmssPTdcYpP/5J/xc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6WmlVKLFFXgWYAGoJosorxzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82 h1:EO13QJTCD1Ig2IrQnoHTRrn981H9mB7afXsZ89WptI4= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82/go.mod h1:AGh1NCg0SH+uyJamiJA5tTQcql4MMRDXGRdMmCxCXzY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 h1:GMYy2EOWfzdP3wfVAGXBNKY5vK4K8vMET4sYOYltmqs= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36/go.mod h1:gDhdAV6wL3PmPqBhiPbnlS447GoWs8HTTOYef9/9Inw= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 h1:nAP2GYbfh8dd2zGZqFRSMlq+/F6cMPBUuCsGAMkN074= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4/go.mod h1:LT10DsiGjLWh4GbjInf9LQejkYEhBgBCjLG5+lvk4EE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 h1:qcLWgdhq45sDM9na4cvXax9dyLitn8EYBRl8Ak4XtG4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17/go.mod h1:M+jkjBFZ2J6DJrjMv2+vkBbuht6kxJYtJiwoVgX4p4U= +github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 h1:JubM8CGDDFaAOmBrd8CRYNr49ZNgEAiLwGwgNMdS0nw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= @@ -192,10 +168,6 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= @@ -209,88 +181,79 @@ github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc= github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= -github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0= -github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= -github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/bytedance/sonic v1.12.8 h1:4xYRVRlXIgvSZ4e8iVTlMF5szgpXd4AfvuWgA8I8lgs= -github.com/bytedance/sonic v1.12.8/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= +github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0= +github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.2.2 h1:jxAJuN9fOot/cyz5Q6dUuMJF5OqQ6+5GfA8FjjQ0R4o= -github.com/bytedance/sonic/loader v0.2.2/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0= github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs= -github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY= -github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY= +github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk= +github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= +github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= +github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI= +github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo= github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8= github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI= -github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= +github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= -github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= @@ -298,45 +261,30 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/ github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c h1:+Zo5Ca9GH0RoeVZQKzFJcTLoAixx5s5Gq3pTIS+n354= github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c/go.mod h1:HJGU9ULdREjOcVGZVPB5s6zYmHi1RxzT71l2wQyLmnE= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= -github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= -github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= -github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +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 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= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230531210528-d7324b2d74f7/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 h1:O7I1iuzEA7SG+dK8ocOBSlYAA9jBUmCYl/Qa7ey7JAM= -github.com/dop251/goja v0.0.0-20240220182346-e401ed450204/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= -github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562 h1:ObbB2tzHWWAxzsG5futqeq2Ual2zYlo/+eMkSc5sn8w= -github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562/go.mod h1:X2TOTJ+Uamd454RFp7ig2tmP3hQg0Z2Qk8gbVQmU0mk= +github.com/dop251/goja v0.0.0-20250624190929-4d26883d182a h1:QIWJoaD2+zxUjN28l8zixmbuvtYqqcxj49Iwzw7mDpk= +github.com/dop251/goja v0.0.0-20250624190929-4d26883d182a/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= +github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 h1:fuHXpEVTTk7TilRdfGRLHpiTD6tnT0ihEowCfWjlFvw= +github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0/go.mod h1:Tb7Xxye4LX7cT3i8YLvmPMGCV92IOi4CDZvm/V8ylc0= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug= -github.com/elazarl/goproxy v1.2.1/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= +github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= +github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -345,59 +293,45 @@ github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b h1:XMw3j+4AEXLeL/uyiZ7/qYE1X7Ul05RTwWBhzxCLi+0= github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b/go.mod h1:l2Jrml4vojDomW5jdDJhIS60KdbrE9uPYhyAq/7OnF4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/gaissmai/bart v0.17.10 h1:TY1y++A6N/ESrwRLTRWrnVOrQpZqpOYSVnKMu/FYW6o= -github.com/gaissmai/bart v0.17.10/go.mod h1:JCPkH/Xt5bSPCKDc6OpzkhSCeib8BIxu3kthzZwcl6w= +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.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.126.0 h1:c2cSgLnAsS0xYfKsgt5oBV6MYRM/giU8/RtwUY4wyfY= -github.com/getkin/kin-openapi v0.126.0/go.mod h1:7mONz8IwmSRg6RttPu6v8U/OJ+gr+J99qSFNjPGSQqw= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= -github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-echarts/go-echarts/v2 v2.3.3 h1:uImZAk6qLkC6F9ju6mZ5SPBqTyK8xjZKwSmwnCg4bxg= -github.com/go-echarts/go-echarts/v2 v2.3.3/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-echarts/go-echarts/v2 v2.6.0 h1:4wEquGT/I7lipHnOCh/z3qa8E4dY0SYFdEEnaTzzzvU= +github.com/go-echarts/go-echarts/v2 v2.6.0/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= -github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= -github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= +github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= +github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-ldap/ldap/v3 v3.4.5 h1:ekEKmaDrpvR2yf5Nc/DClsGG9lAmdDixe44mLzlW5r8= -github.com/go-ldap/ldap/v3 v3.4.5/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU= +github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= @@ -412,76 +346,58 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= -github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA= github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q= github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= 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.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= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= +github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= -github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -493,17 +409,14 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo= @@ -514,78 +427,47 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf h1:umfGUaWdFP2s6457fz1+xXYIWDxdGc7HdkLS9aJ1skk= github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf/go.mod h1:V99KdStnMHZsvVOwIvhfcUzYgYkRZeQWUtumtL+SKxA= github.com/hdm/jarm-go v0.0.7 h1:Eq0geenHrBSYuKrdVhrBdMMzOmA+CAMLzN2WrF3eL6A= @@ -593,25 +475,21 @@ github.com/hdm/jarm-go v0.0.7/go.mod h1:kinGoS0+Sdn1Rr54OtanET5E5n7AlD6T6CrJAKDj github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= -github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= +github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= -github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= -github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= -github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= -github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= -github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA= -github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg= +github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY= +github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= +github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= +github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc= +github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= @@ -629,41 +507,29 @@ github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJk github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ= github.com/kataras/jwt v0.1.10/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kitabisa/go-ci v1.0.3 h1:JmIUIvcercRQc/9x/v02ydCCqU4MadSHaNaOF8T2pGA= github.com/kitabisa/go-ci v1.0.3/go.mod h1:e3wBSzaJbcifXrr/Gw2ZBLn44MmeqP5WySwXyHlCK/U= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -673,11 +539,7 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -686,21 +548,19 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= -github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= +github.com/labstack/echo/v4 v4.13.4 h1:oTZZW+T3s9gAu5L8vmzihV7/lkXGZuITzTQkTEhcXEA= +github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC8rBdndmjQ= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa h1:KQKuQDgA3DZX6C396lt3WDYB9Um1gLITLbvficVbqXk= github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa/go.mod h1:HbwNE4XGwjgtUELkvQaAOjWrpianHYZdQVNqSdYW3UM= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora/v4 v4.0.0 h1:sRjfPpun/63iADiSvGGjgA1cAYegEWMPCJdUpJYn9JA= @@ -711,62 +571,50 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs= github.com/mackerelio/go-osstat v0.2.4/go.mod h1:Zy+qzGdZs3A9cuIqmgbJvwbmLQH9dJvtio5ZjJTbdlQ= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= +github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/mholt/archives v0.1.0 h1:FacgJyrjiuyomTuNA92X5GyRBRZjE43Y/lrzKIlF35Q= -github.com/mholt/archives v0.1.0/go.mod h1:j/Ire/jm42GN7h90F5kzj6hf6ZFzEH66de+hmjEKu+I= +github.com/mholt/archives v0.1.3 h1:aEAaOtNra78G+TvV5ohmXrJOAzf++dIlYeDW3N9q458= +github.com/mholt/archives v0.1.3/go.mod h1:LUCGp++/IbV/I0Xq4SzcIR6uwgeh2yjnQWamjRQfLTU= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= -github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= -github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/microsoft/go-mssqldb v1.9.2 h1:nY8TmFMQOHpm2qVWo6y4I2mAmVdZqlGiMGAYt64Ibbs= +github.com/microsoft/go-mssqldb v1.9.2/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= -github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= +github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= +github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= +github.com/minio/minlz v1.0.0 h1:Kj7aJZ1//LlTP1DM8Jm7lNKvvJS2m74gyyXXn3+uJWQ= +github.com/minio/minlz v1.0.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 h1:yRZGarbxsRytL6EGgbqK2mCY+Lk5MWKQYKJT2gEglhc= github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= @@ -777,24 +625,16 @@ github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1 github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= -github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nwaples/rardecode/v2 v2.0.1 h1:3MN6/R+Y4c7e+21U3yhWuUcf72sYmcmr6jtiuAVSH1A= -github.com/nwaples/rardecode/v2 v2.0.1/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/nwaples/rardecode/v2 v2.1.0 h1:JQl9ZoBPDy+nIZGb1mx8+anfHp/LV3NE2MjMiv0ct/U= +github.com/nwaples/rardecode/v2 v2.1.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -807,67 +647,52 @@ github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeD github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w= -github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runc v1.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19oYB80= +github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM= +github.com/openrdap/rdap v0.9.1 h1:Rv6YbanbiVPsKRvOLdUmlU1AL5+2OFuEFLjFN+mQsCM= +github.com/openrdap/rdap v0.9.1/go.mod h1:vKSiotbsENrjM/vaHXLddXbW8iQkBfa+ldEuYEjyLTQ= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= -github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/ory/dockertest/v3 v3.12.0 h1:3oV9d0sDzlSQfHtIaB5k6ghUCVMVLpAY8hwrqoCyRCw= +github.com/ory/dockertest/v3 v3.12.0/go.mod h1:aKNDTva3cp8dwOWwb9cWuX84aH5akkxXRvO7KCwWVjE= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= -github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/praetorian-inc/fingerprintx v1.1.9 h1:zWbG/Fdan0s/dvXkeaHb/CdFTz/yEEzrAF4iCzok3r8= -github.com/praetorian-inc/fingerprintx v1.1.9/go.mod h1:k6EJIHe/Da4DH5e4JuoZHe+qSGq/KPUmXGaK+xW74OI= +github.com/praetorian-inc/fingerprintx v1.1.15 h1:CVIxrIQARbmdk5h8E9tIJZbvFoY2sGLLG9rpFVfQqpA= +github.com/praetorian-inc/fingerprintx v1.1.15/go.mod h1:hqRroITBwKpP8BOGF+n/A+qv9wSF7OSVinmu5NCyOUI= github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kID2iwsDqI= github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.17 h1:YSqKk05+UGSxmPIp7tlCvRegF63FUqO+mA2Wl/Je3gA= -github.com/projectdiscovery/cdncheck v1.1.17/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.15 h1:rRs3LW2MP7V8QeONVRYce6RhDcWp83O+AWmt+QQ4mBM= +github.com/projectdiscovery/cdncheck v1.1.15/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= -github.com/projectdiscovery/dsl v0.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI= -github.com/projectdiscovery/dsl v0.4.2/go.mod h1:J1RizRF6O3lvk2v8p/tLAYqaxWg6N52OWc+uS5ZmO2U= -github.com/projectdiscovery/dsl v0.4.3 h1:ZrbRkyK38hRiYMX7s6ohaTorDpq321ErqJuBUDmh49g= -github.com/projectdiscovery/dsl v0.4.3/go.mod h1:cyt2IaYhS5SlyZ1D2BdK0QwIBXQW/u9zaBmRAKYKAmk= -github.com/projectdiscovery/fastdialer v0.4.0 h1:licZKyq+Shd5lLDb8uPd60Jp43K4NFE8cr67XD2eg7w= -github.com/projectdiscovery/fastdialer v0.4.0/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ= +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.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= github.com/projectdiscovery/freeport v0.0.7/go.mod h1:cOhWKvNBe9xM6dFJ3RrrLvJ5vXx2NQ36SecuwjenV2k= +github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c h1:s+lLAlrOrgwlPZQ9DFqNw+kia2nteKnJZ2Ek313yoUc= +github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c/go.mod h1:rN35/D3lVx2YDeENFFz06uj8j3XIqK1Ym9XcISF5fzg= github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG906Drtbpz4DwU5mhGIeOhRcktDH4cGQitGUMAsg= github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY= github.com/projectdiscovery/goflags v0.1.74 h1:n85uTRj5qMosm0PFBfsvOL24I7TdWRcWq/1GynhXS7c= @@ -878,8 +703,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.88 h1:ygPNJOmw8Bc0Pu1+fa/foNBatSuSTwsUQLA8xBiCayI= -github.com/projectdiscovery/hmap v0.0.88/go.mod h1:ZrAtCoXdrYsYdlk/XslYFyuiDHkohmsQhvaLlN9cRRY= +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= @@ -892,93 +717,55 @@ 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.14 h1:XnwpGjF+h9xgwEIgrFG3G+7cGRPwh6FkxgQaLuw4rv4= -github.com/projectdiscovery/networkpolicy v0.1.14/go.mod h1:pat2rE4G7kbow8CQ/yOym0bdLPq8rj7ZZWn3/3OT4Rs= -github.com/projectdiscovery/ratelimit v0.0.80 h1:kDZ9Rgd/EiDR3fw8Ugtp4xVMaMZNzlEO8zCD4QholaE= -github.com/projectdiscovery/ratelimit v0.0.80/go.mod h1:UW6g3VZbX+wI6WLXsexWGpSYnaQ79Uv+VewRj2+pzXQ= +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.1-0.20221108103045-9865884d1917 h1:m03X4gBVSorSzvmm0bFa7gDV4QNSOWPL/fgZ4kTXBxk= -github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg= -github.com/projectdiscovery/retryabledns v1.0.99 h1:DJ6TewgkwqJozDOPXhoOy/cdtuzJzbIQ/BFfWNYzHpw= -github.com/projectdiscovery/retryabledns v1.0.99/go.mod h1:pkPYuqtxhX6z1pYL+O6s4Lg7ubINt2jg12gsaW9O3kY= -github.com/projectdiscovery/retryablehttp-go v1.0.111 h1:HzkVN0IyC0RfVylBlgNoqaQgVvuUEvbDEVbpGyD/Y9M= -github.com/projectdiscovery/retryablehttp-go v1.0.111/go.mod h1:Tl6noELU9RpjwywMDw722HB038QXohl90g2ZtKSqbCI= +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.103 h1:rPnoMTK+CXLbO8kT7ODtwbhyQGAUpJsqhVq8AAvu1bs= +github.com/projectdiscovery/retryabledns v1.0.103/go.mod h1:sfu91YrZkb8Ccvij8YDTV96cQt69IPqnfa+OEFUke1o= +github.com/projectdiscovery/retryablehttp-go v1.0.116 h1:yjgT5q6lGkZ7gkuuHe5wm2mmq9tE5t23PSk6sz3F6/E= +github.com/projectdiscovery/retryablehttp-go v1.0.116/go.mod h1:GUMjLgc9hJtIzx34igabPtem98ewhq2xEG8TZmhefog= 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= github.com/projectdiscovery/stringsutil v0.0.2/go.mod h1:EJ3w6bC5fBYjVou6ryzodQq37D5c6qbAYQpGmAy+DC0= github.com/projectdiscovery/tlsx v1.1.9 h1:DhErhHCO2+toF5DEX7qe3pkwrIrYlex3F/mzHEUiZHg= github.com/projectdiscovery/tlsx v1.1.9/go.mod h1:Jy+r38WyYjapQWaffiKGdYm4Ksdrt8BWtsqA2rUospU= -github.com/projectdiscovery/uncover v1.0.10 h1:FdnBYgynGUtjIsW5WPIIhadR1Smcghik9cZSMEtILN4= -github.com/projectdiscovery/uncover v1.0.10/go.mod h1:l7QQ+mBc7bLK4tqYqPyo9nrYdz1K8vaGZWKYihkHmAs= -github.com/projectdiscovery/useragent v0.0.100 h1:gDZSgPQCP8D0XUny41Ch4urP+FK5OcM5TB1btwCg4Gk= -github.com/projectdiscovery/useragent v0.0.100/go.mod h1:8je9oUPzT5R+gjKQNEFurDSvX7fCnqW2iDGYdKMH6hY= -github.com/projectdiscovery/utils v0.4.19 h1:rWOOTWUMQK9gvgH01rrw0qFi0hrh712hM1pCUzapCqA= -github.com/projectdiscovery/utils v0.4.19/go.mod h1:y5gnpQn802iEWqf0djTRNskJlS62P5eqe1VS1+ah0tk= -github.com/projectdiscovery/wappalyzergo v0.2.28 h1:fd4xne6ndxJFSqJfSDAXmR3G87SZQdOYFTapHk4Ksh4= -github.com/projectdiscovery/wappalyzergo v0.2.28/go.mod h1:F8X79ljvmvrG+EIxdxWS9VbdkVTsQupHYz+kXlp8O0o= +github.com/projectdiscovery/uncover v1.1.0 h1:UDp/qLZn78YZb6VPoOrfyP1vz+ojEx8VrTTyjjRt9UU= +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.21 h1:yAothTUSF6NwZ9yoC4iGe5gSBrovqKR9JwwW3msxk3Q= +github.com/projectdiscovery/utils v0.4.21/go.mod h1:HJuJFqjB6EmVaDl0ilFPKvLoMaX2GyE6Il2TqKXNs8I= +github.com/projectdiscovery/wappalyzergo v0.2.35 h1:4LN5Paa4l5Z5Q5XYwNlF0cRsx1ojYeY5EELEMpk8grw= +github.com/projectdiscovery/wappalyzergo v0.2.35/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= -github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= -github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= -github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= +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.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= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sashabaranov/go-openai v1.37.0 h1:hQQowgYm4OXJ1Z/wTrE+XZaO20BYsL0R3uRPSpfNZkY= github.com/sashabaranov/go-openai v1.37.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/seh-msft/burpxml v1.0.1 h1:5G3QPSzvfA1WcX7LkxmKBmK2RnNyGviGWnJPumE0nwg= @@ -987,44 +774,33 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y= -github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk= +github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= +github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= -github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg= github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= +github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -1036,17 +812,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 h1:GXIyLuIJ5Qk46lI8WJ83qHBZKUI3zhmMmuoY9HICUIQ= github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9/go.mod h1:uQdBQGrE1fZ2EyOs0pLcCDd1bBV4rSThieuIIGhXZ50= -github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= -github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI= github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= @@ -1075,35 +846,27 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= +github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= 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.2 h1:LlnoSH0Eqbsi3ReXZWBKCK5lHyzf3sc1JEHH1cnlfho= -github.com/weppos/publicsuffix-go v0.40.2/go.mod h1:XsLZnULC3EJ1Gvk9GVjuCTZ8QUu9ufE4TZpOizDShko= -github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE= +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/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= -github.com/xanzy/go-gitlab v0.107.0 h1:P2CT9Uy9yN9lJo3FLxpMZ4xj6uWcpnigXsjvqJ6nd2Y= -github.com/xanzy/go-gitlab v0.107.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -1119,12 +882,14 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/yassinebenaid/godump v0.10.0 h1:FolBA+Ix5uwUiXYBBYOsf1VkT5+0f4gtFNTkYTiIR08= -github.com/yassinebenaid/godump v0.10.0/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44= +github.com/yassinebenaid/godump v0.11.1 h1:SPujx/XaYqGDfmNh7JI3dOyCUVrG0bG2duhO3Eh2EhI= +github.com/yassinebenaid/godump v0.11.1/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44= github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU= github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= @@ -1143,16 +908,14 @@ github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU= github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= -github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= -github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= +github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= +github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk= +github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zcalusic/sysinfo v1.0.2 h1:nwTTo2a+WQ0NXwo0BGRojOJvJ/5XKvQih+2RrtWqfxc= @@ -1170,47 +933,34 @@ github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54t github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk= github.com/zmap/zcrypto v0.0.0-20201128221613-3719af1573cf/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ= github.com/zmap/zcrypto v0.0.0-20201211161100-e54a5822fb7e/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ= -github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300/go.mod h1:mOd4yUMgn2fe2nV9KXsa9AyQBFZGzygVPovsZR+Rl5w= github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db h1:IfONOhyZlf4qPt3ENPU+27mBbPjzTQ+swKpj7MJva9I= github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db/go.mod h1:mo/07mo6reDaiz6BzveCuYBWb1d+aX8Pf8Nh+Q57y2g= -github.com/zmap/zflags v1.4.0-beta.1.0.20200204220219-9d95409821b6/go.mod h1:HXDUD+uue8yeLHr0eXx1lvY6CvMiHbTKw5nGmA9OUoo= -github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706 h1:LaMyYFWQA7kh3ovPfAaFDTKlJu3JGng8khruOtsBVnE= -github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706/go.mod h1:re2kMcs84XHb8Xl6RInt0emoKCuphfmfjHYuteviLHQ= +github.com/zmap/zgrab2 v0.2.0 h1:j48+zkSw4rbvQOq9em5MnPxwP5QyUmzTXSCtQzZ2MnI= +github.com/zmap/zgrab2 v0.2.0/go.mod h1:vM5eYaxZTjIGZe9oijtxjU4EfucELIr9mbG7Chxmn2I= github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +gitlab.com/gitlab-org/api/client-go v0.130.1 h1:1xF5C5Zq3sFeNg3PzS2z63oqrxifne3n/OnbI7nptRc= +gitlab.com/gitlab-org/api/client-go v0.130.1/go.mod h1:ZhSxLAWadqP6J9lMh40IAZOlOxBLPRh7yFOXR/bMJWM= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r40k= -go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= +go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= goftp.io/server/v2 v2.0.1 h1:H+9UbCX2N206ePDSVNCjBftOKOgil6kQ5RAQNx5hJwE= goftp.io/server/v2 v2.0.1/go.mod h1:7+H/EIq7tXdfo1Muu5p+l3oQ6rYkDZ8lY7IM5d5kVdQ= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1225,7 +975,6 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= @@ -1233,10 +982,9 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1244,11 +992,9 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= -golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1260,13 +1006,11 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -1274,17 +1018,12 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1292,37 +1031,20 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= @@ -1331,21 +1053,17 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= -golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1353,26 +1071,18 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1382,30 +1092,14 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1413,21 +1107,15 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1436,16 +1124,14 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= @@ -1453,10 +1139,9 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1466,25 +1151,19 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1501,48 +1180,28 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1551,28 +1210,17 @@ google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1580,58 +1228,20 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1639,50 +1249,38 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/corvus-ch/zbase32.v1 v1.0.0 h1:K4u1NprbDNvKPczKfHLbwdOWHTZ0zfv2ow71H1nRnFU= gopkg.in/corvus-ch/zbase32.v1 v1.0.0/go.mod h1:T3oKkPOm4AV/bNXCNFUxRmlE9RUyBz/DSo0nK9U+c0Y= gopkg.in/djherbis/times.v1 v1.3.0 h1:uxMS4iMtH6Pwsxog094W0FYldiNnfY/xba00vq6C2+o= gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv6mUY0P8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= -gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= -mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= +mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0= +mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY= moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/internal/pdcp/writer.go b/internal/pdcp/writer.go index e4e8e25bb..fb3c058d1 100644 --- a/internal/pdcp/writer.go +++ b/internal/pdcp/writer.go @@ -127,7 +127,9 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { // continuously read from the reader and send to channel go func() { - defer r.Close() + defer func() { + _ = r.Close() + }() defer close(ch) for { data, err := reader.ReadString('\n') @@ -213,7 +215,9 @@ func (u *UploadWriter) upload(data []byte) error { if err != nil { return errorutil.NewWithErr(err).Msgf("could not upload results") } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() bin, err := io.ReadAll(resp.Body) if err != nil { return errorutil.NewWithErr(err).Msgf("could not get id from response") @@ -251,10 +255,10 @@ func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) { return nil, errorutil.NewWithErr(err).Msgf("could not create cloud upload request") } // add pdtm meta params - req.URL.Params.Merge(updateutils.GetpdtmParams(config.Version)) + req.Params.Merge(updateutils.GetpdtmParams(config.Version)) // if it is upload endpoint also include name if it exists - if u.scanName != "" && req.URL.Path == uploadEndpoint { - req.URL.Params.Add("name", u.scanName) + if u.scanName != "" && req.Path == uploadEndpoint { + req.Params.Add("name", u.scanName) } req.URL.Update() diff --git a/internal/runner/healthcheck.go b/internal/runner/healthcheck.go index da85bd5a4..627b55cb1 100644 --- a/internal/runner/healthcheck.go +++ b/internal/runner/healthcheck.go @@ -47,7 +47,7 @@ func DoHealthCheck(options *types.Options) string { } c4, err := net.Dial("tcp4", "scanme.sh:80") if err == nil && c4 != nil { - c4.Close() + _ = c4.Close() } testResult = "Ok" if err != nil { @@ -56,7 +56,7 @@ func DoHealthCheck(options *types.Options) string { test.WriteString(fmt.Sprintf("IPv4 connectivity to scanme.sh:80 => %s\n", testResult)) c6, err := net.Dial("tcp6", "scanme.sh:80") if err == nil && c6 != nil { - c6.Close() + _ = c6.Close() } testResult = "Ok" if err != nil { @@ -65,7 +65,7 @@ func DoHealthCheck(options *types.Options) string { test.WriteString(fmt.Sprintf("IPv6 connectivity to scanme.sh:80 => %s\n", testResult)) u4, err := net.Dial("udp4", "scanme.sh:53") if err == nil && u4 != nil { - u4.Close() + _ = u4.Close() } testResult = "Ok" if err != nil { diff --git a/internal/runner/options.go b/internal/runner/options.go index 56612d153..57b28973b 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -122,7 +122,7 @@ func ParseOptions(options *types.Options) { // Set GitHub token in env variable. runner.getGHClientWithToken() reads token from env if options.GitHubToken != "" && os.Getenv("GITHUB_TOKEN") != options.GitHubToken { - os.Setenv("GITHUB_TOKEN", options.GitHubToken) + _ = os.Setenv("GITHUB_TOKEN", options.GitHubToken) } if options.UncoverQuery != nil { @@ -304,7 +304,9 @@ func createReportingOptions(options *types.Options) (*reporting.Options, error) if err != nil { return nil, errors.Wrap(err, "could not open reporting config file") } - defer file.Close() + defer func() { + _ = file.Close() + }() if err := yaml.DecodeAndValidate(file, reportingOptions); err != nil { return nil, errors.Wrap(err, "could not parse reporting config file") @@ -380,7 +382,9 @@ func loadResolvers(options *types.Options) { if err != nil { gologger.Fatal().Msgf("Could not open resolvers file: %s\n", err) } - defer file.Close() + defer func() { + _ = file.Close() + }() scanner := bufio.NewScanner(file) for scanner.Scan() { diff --git a/internal/runner/proxy.go b/internal/runner/proxy.go index 6160f5481..ca6a6dbba 100644 --- a/internal/runner/proxy.go +++ b/internal/runner/proxy.go @@ -30,7 +30,9 @@ func loadProxyServers(options *types.Options) error { if err != nil { return fmt.Errorf("could not open proxy file: %w", err) } - defer file.Close() + defer func() { + _ = file.Close() + }() scanner := bufio.NewScanner(file) for scanner.Scan() { proxy := scanner.Text() @@ -52,12 +54,13 @@ func loadProxyServers(options *types.Options) error { return errorutil.WrapfWithNil(err, "failed to parse proxy got %v", err) } if options.ProxyInternal { - os.Setenv(HTTP_PROXY_ENV, proxyURL.String()) + _ = os.Setenv(HTTP_PROXY_ENV, proxyURL.String()) } - if proxyURL.Scheme == proxyutils.HTTP || proxyURL.Scheme == proxyutils.HTTPS { + switch proxyURL.Scheme { + case proxyutils.HTTP, proxyutils.HTTPS: gologger.Verbose().Msgf("Using %s as proxy server", proxyURL.String()) options.AliveHttpProxy = proxyURL.String() - } else if proxyURL.Scheme == proxyutils.SOCKS5 { + case proxyutils.SOCKS5: options.AliveSocksProxy = proxyURL.String() gologger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String()) } diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 424d27116..b046443b0 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -439,7 +439,7 @@ func (r *Runner) setupPDCPUpload(writer output.Writer) output.Writer { if r.options.ScanID != "" { r.options.EnableCloudUpload = true } - if !(r.options.EnableCloudUpload || EnableCloudUpload) { + if !r.options.EnableCloudUpload && !EnableCloudUpload { r.pdcpUploadErrMsg = fmt.Sprintf("[%v] Scan results upload to cloud is disabled.", r.colorizer.BrightYellow("WRN")) return writer } @@ -863,8 +863,8 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) { return fmt.Sprintf("Current %s version: %v %v", versionType, version, updateutils.GetVersionDescription(version, latestVersion)) } - gologger.Info().Msgf(versionInfo(config.Version, cfg.LatestNucleiVersion, "nuclei")) - gologger.Info().Msgf(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates")) + gologger.Info().Msg(versionInfo(config.Version, cfg.LatestNucleiVersion, "nuclei")) + gologger.Info().Msg(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates")) if !HideAutoSaveMsg { if r.pdcpUploadErrMsg != "" { gologger.Print().Msgf("%s", r.pdcpUploadErrMsg) @@ -940,7 +940,9 @@ func UploadResultsToCloud(options *types.Options) error { if err != nil { return errors.Wrap(err, "could not open scan upload file") } - defer file.Close() + defer func() { + _ = file.Close() + }() gologger.Info().Msgf("Uploading scan results to cloud dashboard from %s", options.ScanUploadFile) dec := json.NewDecoder(file) diff --git a/internal/runner/runner_test.go b/internal/runner/runner_test.go index 5fc89ae0a..60b3df9d5 100644 --- a/internal/runner/runner_test.go +++ b/internal/runner/runner_test.go @@ -64,8 +64,8 @@ func TestWalkReflectStructAssignsEnvVars(t *testing.T) { B: "$VAR_TWO", }, } - os.Setenv("VAR_EXAMPLE", "value") - os.Setenv("VAR_TWO", "value2") + _ = os.Setenv("VAR_EXAMPLE", "value") + _ = os.Setenv("VAR_TWO", "value2") Walk(testStruct, expandEndVars) @@ -79,9 +79,9 @@ func TestWalkReflectStructHandlesDifferentTypes(t *testing.T) { B: "$VAR_TWO", C: "$VAR_THREE", } - os.Setenv("VAR_EXAMPLE", "value") - os.Setenv("VAR_TWO", "2") - os.Setenv("VAR_THREE", "true") + _ = os.Setenv("VAR_EXAMPLE", "value") + _ = os.Setenv("VAR_TWO", "2") + _ = os.Setenv("VAR_THREE", "true") Walk(testStruct, expandEndVars) @@ -96,9 +96,9 @@ func TestWalkReflectStructEmpty(t *testing.T) { B: "", C: "$VAR_THREE", } - os.Setenv("VAR_EXAMPLE", "value") - os.Setenv("VAR_TWO", "2") - os.Setenv("VAR_THREE", "true") + _ = os.Setenv("VAR_EXAMPLE", "value") + _ = os.Setenv("VAR_TWO", "2") + _ = os.Setenv("VAR_THREE", "true") Walk(testStruct, expandEndVars) @@ -116,7 +116,7 @@ func TestWalkReflectStructWithNoYamlTag(t *testing.T) { C: "$GITHUB_USER", } - os.Setenv("GITHUB_USER", "testuser") + _ = os.Setenv("GITHUB_USER", "testuser") Walk(test, expandEndVars) require.Equal(t, "testuser", test.A) @@ -132,9 +132,9 @@ func TestWalkReflectStructHandlesNestedStructs(t *testing.T) { C: "$VAR_THREE", }, } - os.Setenv("VAR_EXAMPLE", "value") - os.Setenv("VAR_TWO", "2") - os.Setenv("VAR_THREE", "true") + _ = os.Setenv("VAR_EXAMPLE", "value") + _ = os.Setenv("VAR_TWO", "2") + _ = os.Setenv("VAR_THREE", "true") Walk(testStruct, expandEndVars) diff --git a/internal/server/server.go b/internal/server/server.go index 259923272..9e297fce2 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -125,7 +125,7 @@ func NewStatsServer(fuzzStatsDB *stats.Tracker) (*DASTServer, error) { func (s *DASTServer) Close() { s.nucleiExecutor.Close() - s.echo.Close() + _ = s.echo.Close() s.tasksPool.StopAndWaitFor(1 * time.Minute) } diff --git a/pkg/authprovider/authx/dynamic.go b/pkg/authprovider/authx/dynamic.go index f3e361e41..a3abc2204 100644 --- a/pkg/authprovider/authx/dynamic.go +++ b/pkg/authprovider/authx/dynamic.go @@ -43,8 +43,8 @@ func (d *Dynamic) GetDomainAndDomainRegex() ([]string, []string) { domainRegex = append(domainRegex, secret.DomainsRegex...) } if d.Secret != nil { - domains = append(domains, d.Secret.Domains...) - domainRegex = append(domainRegex, d.Secret.DomainsRegex...) + domains = append(domains, d.Domains...) + domainRegex = append(domainRegex, d.DomainsRegex...) } uniqueDomains := sliceutil.Dedupe(domains) uniqueDomainRegex := sliceutil.Dedupe(domainRegex) @@ -79,7 +79,7 @@ func (d *Dynamic) Validate() error { } if d.Secret != nil { - d.Secret.skipCookieParse = true // skip cookie parsing in dynamic secrets during validation + d.skipCookieParse = true // skip cookie parsing in dynamic secrets during validation if err := d.Secret.Validate(); err != nil { return err } @@ -192,7 +192,7 @@ func (d *Dynamic) GetStrategies() []AuthStrategy { } var strategies []AuthStrategy if d.Secret != nil { - strategies = append(strategies, d.Secret.GetStrategy()) + strategies = append(strategies, d.GetStrategy()) } for _, secret := range d.Secrets { strategies = append(strategies, secret.GetStrategy()) diff --git a/pkg/authprovider/authx/dynamic_test.go b/pkg/authprovider/authx/dynamic_test.go index 05bf9c134..ffa38ea83 100644 --- a/pkg/authprovider/authx/dynamic_test.go +++ b/pkg/authprovider/authx/dynamic_test.go @@ -36,10 +36,10 @@ func TestDynamicUnmarshalJSON(t *testing.T) { // Secret require.NotNil(t, d.Secret) - require.Equal(t, "BasicAuth", d.Secret.Type) - require.Equal(t, []string{"test.com"}, d.Secret.Domains) - require.Equal(t, "testuser", d.Secret.Username) - require.Equal(t, "testpass", d.Secret.Password) + require.Equal(t, "BasicAuth", d.Type) + require.Equal(t, []string{"test.com"}, d.Domains) + require.Equal(t, "testuser", d.Username) + require.Equal(t, "testpass", d.Password) // Dynamic fields require.Equal(t, "test-template.yaml", d.TemplatePath) @@ -90,9 +90,9 @@ func TestDynamicUnmarshalJSON(t *testing.T) { // Secret require.NotNil(t, d.Secret) - require.Equal(t, "HeadersAuth", d.Secret.Type) - require.Equal(t, []string{"api.test.com"}, d.Secret.Domains) - require.Len(t, d.Secret.Headers, 1) + require.Equal(t, "HeadersAuth", d.Type) + require.Equal(t, []string{"api.test.com"}, d.Domains) + require.Len(t, d.Headers, 1) require.Equal(t, "X-API-Key", d.Secret.Headers[0].Key) require.Equal(t, "secret-key", d.Secret.Headers[0].Value) diff --git a/pkg/catalog/config/ignorefile.go b/pkg/catalog/config/ignorefile.go index b8a03544f..14c0ec30f 100644 --- a/pkg/catalog/config/ignorefile.go +++ b/pkg/catalog/config/ignorefile.go @@ -20,7 +20,9 @@ func ReadIgnoreFile() IgnoreFile { gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n", err) return IgnoreFile{} } - defer file.Close() + defer func() { + _ = file.Close() + }() ignore := IgnoreFile{} if err := yaml.NewDecoder(file).Decode(&ignore); err != nil { diff --git a/pkg/catalog/config/template.go b/pkg/catalog/config/template.go index c35bef664..ecb93e283 100644 --- a/pkg/catalog/config/template.go +++ b/pkg/catalog/config/template.go @@ -74,7 +74,9 @@ func getTemplateID(filePath string) (string, error) { return "", err } - defer file.Close() + defer func() { + _ = file.Close() + }() return GetTemplateIDFromReader(file, filePath) } diff --git a/pkg/catalog/loader/ai_loader.go b/pkg/catalog/loader/ai_loader.go index 64af39939..ce12e90b1 100644 --- a/pkg/catalog/loader/ai_loader.go +++ b/pkg/catalog/loader/ai_loader.go @@ -117,7 +117,9 @@ func generateAITemplate(prompt string) (string, string, error) { if err != nil { return "", "", errorutil.New("Failed to send HTTP request: %v", err) } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if resp.StatusCode == http.StatusUnauthorized { return "", "", errorutil.New("Invalid API Key or API Key not configured, Create one for free at https://cloud.projectdiscovery.io/") diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index b9b145cf4..98039117d 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -237,7 +237,9 @@ func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error) if err != nil { return nil, err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() return io.ReadAll(resp.Body) } else { return os.ReadFile(uri) diff --git a/pkg/catalog/loader/remote_loader.go b/pkg/catalog/loader/remote_loader.go index 898ca37d9..749d19d91 100644 --- a/pkg/catalog/loader/remote_loader.go +++ b/pkg/catalog/loader/remote_loader.go @@ -49,9 +49,10 @@ func getRemoteTemplatesAndWorkflows(templateURLs, workflowURLs, remoteTemplateDo err = remoteContent.Error } } else { - if remoteContent.Type == Template { + switch remoteContent.Type { + case Template: remoteTemplateList = append(remoteTemplateList, remoteContent.Content...) - } else if remoteContent.Type == Workflow { + case Workflow: remoteWorkFlowList = append(remoteWorkFlowList, remoteContent.Content...) } } @@ -80,7 +81,9 @@ func getRemoteContent(URL string, remoteTemplateDomainList []string, remoteConte } return } - defer response.Body.Close() + defer func() { + _ = response.Body.Close() + }() if response.StatusCode < 200 || response.StatusCode > 299 { remoteContentChannel <- RemoteContent{ Error: fmt.Errorf("get \"%s\": unexpect status %d", URL, response.StatusCode), diff --git a/pkg/external/customtemplates/gitlab.go b/pkg/external/customtemplates/gitlab.go index fbb9a61ce..169928bef 100644 --- a/pkg/external/customtemplates/gitlab.go +++ b/pkg/external/customtemplates/gitlab.go @@ -10,7 +10,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" - "github.com/xanzy/go-gitlab" + gitlab "gitlab.com/gitlab-org/api/client-go" ) var _ Provider = &customTemplateGitLabRepo{} diff --git a/pkg/external/customtemplates/s3.go b/pkg/external/customtemplates/s3.go index 1b14206e3..29bb465fd 100644 --- a/pkg/external/customtemplates/s3.go +++ b/pkg/external/customtemplates/s3.go @@ -96,7 +96,9 @@ func downloadToFile(downloader *manager.Downloader, targetDirectory, bucket, key if err != nil { return err } - defer fd.Close() + defer func() { + _ = fd.Close() + }() // Download the file using the AWS SDK for Go _, err = downloader.Download(context.TODO(), fd, &s3.GetObjectInput{Bucket: &bucket, Key: &key}) diff --git a/pkg/fuzz/analyzers/time/analyzer.go b/pkg/fuzz/analyzers/time/analyzer.go index cdf40e6bf..e0710d5e6 100644 --- a/pkg/fuzz/analyzers/time/analyzer.go +++ b/pkg/fuzz/analyzers/time/analyzer.go @@ -123,7 +123,7 @@ func (a *Analyzer) Analyze(options *analyzers.Options) (bool, string, error) { if err != nil { return 0, errors.Wrap(err, "could not rebuild request") } - gologger.Verbose().Msgf("[%s] Sending request with %d delay for: %s", a.Name(), delay, rebuilt.URL.String()) + gologger.Verbose().Msgf("[%s] Sending request with %d delay for: %s", a.Name(), delay, rebuilt.String()) timeTaken, err := doHTTPRequestWithTimeTracing(rebuilt, options.HttpClient) if err != nil { diff --git a/pkg/fuzz/analyzers/time/time_delay.go b/pkg/fuzz/analyzers/time/time_delay.go index 6ee46bf9e..7349be935 100644 --- a/pkg/fuzz/analyzers/time/time_delay.go +++ b/pkg/fuzz/analyzers/time/time_delay.go @@ -60,10 +60,7 @@ func checkTimingDependency( requestsLeft := requestsLimit var requestsSent []requestsSentMetadata - for { - if requestsLeft <= 0 { - break - } + for requestsLeft > 0 { isCorrelationPossible, delayRecieved, err := sendRequestAndTestConfidence(regression, highSleepTimeSeconds, requestSender, baselineDelay) if err != nil { diff --git a/pkg/fuzz/component/path.go b/pkg/fuzz/component/path.go index ec9ab5d03..e77429c19 100644 --- a/pkg/fuzz/component/path.go +++ b/pkg/fuzz/component/path.go @@ -36,7 +36,7 @@ func (q *Path) Parse(req *retryablehttp.Request) (bool, error) { q.req = req q.value = NewValue("") - splitted := strings.Split(req.URL.Path, "/") + splitted := strings.Split(req.Path, "/") values := make(map[string]interface{}) for i := range splitted { pathTillNow := strings.Join(splitted[:i+1], "/") @@ -83,7 +83,7 @@ func (q *Path) Delete(key string) error { // component rebuilt func (q *Path) Rebuild() (*retryablehttp.Request, error) { originalValues := mapsutil.Map[string, any]{} - splitted := strings.Split(q.req.URL.Path, "/") + splitted := strings.Split(q.req.Path, "/") for i := range splitted { pathTillNow := strings.Join(splitted[:i+1], "/") if pathTillNow == "" { @@ -92,7 +92,7 @@ func (q *Path) Rebuild() (*retryablehttp.Request, error) { originalValues[strconv.Itoa(i)] = pathTillNow } - originalPath := q.req.URL.Path + originalPath := q.req.Path lengthSplitted := len(q.value.parsed.Map) for i := lengthSplitted; i > 0; i-- { key := strconv.Itoa(i) @@ -120,7 +120,7 @@ func (q *Path) Rebuild() (*retryablehttp.Request, error) { // Clone the request and update the path cloned := q.req.Clone(context.Background()) if err := cloned.UpdateRelPath(rebuiltPath, true); err != nil { - cloned.URL.RawPath = rebuiltPath + cloned.RawPath = rebuiltPath } return cloned, nil } diff --git a/pkg/fuzz/component/path_test.go b/pkg/fuzz/component/path_test.go index c47f81f4f..bf1f2f2aa 100644 --- a/pkg/fuzz/component/path_test.go +++ b/pkg/fuzz/component/path_test.go @@ -40,8 +40,8 @@ func TestURLComponent(t *testing.T) { if err != nil { t.Fatal(err) } - require.Equal(t, "/newpath", rebuilt.URL.Path, "unexpected URL path") - require.Equal(t, "https://example.com/newpath", rebuilt.URL.String(), "unexpected full URL") + require.Equal(t, "/newpath", rebuilt.Path, "unexpected URL path") + require.Equal(t, "https://example.com/newpath", rebuilt.String(), "unexpected full URL") } func TestURLComponent_NestedPaths(t *testing.T) { @@ -74,7 +74,7 @@ func TestURLComponent_NestedPaths(t *testing.T) { if err != nil { t.Fatal(err) } - if newReq.URL.Path != "/user/753'/profile" { + if newReq.Path != "/user/753'/profile" { t.Fatal("expected path to be modified") } } diff --git a/pkg/fuzz/component/query.go b/pkg/fuzz/component/query.go index 571161ee1..0fb7ba7cf 100644 --- a/pkg/fuzz/component/query.go +++ b/pkg/fuzz/component/query.go @@ -84,7 +84,7 @@ func (q *Query) Rebuild() (*retryablehttp.Request, error) { return nil, errors.Wrap(err, "could not encode query") } cloned := q.req.Clone(context.Background()) - cloned.URL.RawQuery = encoded + cloned.RawQuery = encoded // Clear the query parameters and re-add them cloned.Params = nil diff --git a/pkg/fuzz/component/query_test.go b/pkg/fuzz/component/query_test.go index 48fe5aa26..00d93c69d 100644 --- a/pkg/fuzz/component/query_test.go +++ b/pkg/fuzz/component/query_test.go @@ -41,6 +41,6 @@ func TestQueryComponent(t *testing.T) { t.Fatal(err) } - require.Equal(t, "foo=baz", rebuilt.URL.RawQuery, "unexpected query string") - require.Equal(t, "https://example.com?foo=baz", rebuilt.URL.String(), "unexpected url") + require.Equal(t, "foo=baz", rebuilt.RawQuery, "unexpected query string") + require.Equal(t, "https://example.com?foo=baz", rebuilt.String(), "unexpected url") } diff --git a/pkg/fuzz/dataformat/multipart.go b/pkg/fuzz/dataformat/multipart.go index 227025d22..20f25a6e7 100644 --- a/pkg/fuzz/dataformat/multipart.go +++ b/pkg/fuzz/dataformat/multipart.go @@ -92,7 +92,7 @@ func (m *MultiPartForm) Encode(data KV) (string, error) { return "", Itererr } - w.Close() + _ = w.Close() return b.String(), nil } @@ -142,7 +142,9 @@ func (m *MultiPartForm) Decode(data string) (KV, error) { if err != nil { return KV{}, err } - defer file.Close() + defer func() { + _ = file.Close() + }() buffer := new(bytes.Buffer) if _, err := buffer.ReadFrom(file); err != nil { diff --git a/pkg/fuzz/execute.go b/pkg/fuzz/execute.go index ea4a3e0fb..8da89d0ea 100644 --- a/pkg/fuzz/execute.go +++ b/pkg/fuzz/execute.go @@ -98,7 +98,7 @@ func (rule *Rule) Execute(input *ExecuteRuleInput) (err error) { // match rule part with component name displayDebugFuzzPoints := make(map[string]map[string]string) for _, componentName := range component.Components { - if !(rule.Part == componentName || sliceutil.Contains(rule.Parts, componentName) || rule.partType == requestPartType) { + if rule.Part != componentName && !sliceutil.Contains(rule.Parts, componentName) && rule.partType != requestPartType { continue } component := component.New(componentName) diff --git a/pkg/fuzz/parts.go b/pkg/fuzz/parts.go index 59ac6e3ca..7d0b51afe 100644 --- a/pkg/fuzz/parts.go +++ b/pkg/fuzz/parts.go @@ -163,7 +163,7 @@ func (rule *Rule) execWithInput(input *ExecuteRuleInput, httpReq *retryablehttp. if rule.options.FuzzParamsFrequency != nil { if rule.options.FuzzParamsFrequency.IsParameterFrequent( parameter, - httpReq.URL.String(), + httpReq.String(), rule.options.TemplateID, ) { return nil diff --git a/pkg/fuzz/stats/stats.go b/pkg/fuzz/stats/stats.go index 87ed5c379..a6c7f9e12 100644 --- a/pkg/fuzz/stats/stats.go +++ b/pkg/fuzz/stats/stats.go @@ -96,9 +96,10 @@ func getCorrectSiteName(originalURL string) string { // Site is the host:port combo siteName := parsed.Host if parsed.Port() == "" { - if parsed.Scheme == "https" { + switch parsed.Scheme { + case "https": siteName = fmt.Sprintf("%s:443", siteName) - } else if parsed.Scheme == "http" { + case "http": siteName = fmt.Sprintf("%s:80", siteName) } } diff --git a/pkg/input/formats/burp/burp_test.go b/pkg/input/formats/burp/burp_test.go index 97e80c534..4245e505c 100644 --- a/pkg/input/formats/burp/burp_test.go +++ b/pkg/input/formats/burp/burp_test.go @@ -17,7 +17,9 @@ func TestBurpParse(t *testing.T) { file, err := os.Open(proxifyInputFile) require.Nilf(t, err, "error opening proxify input file: %v", err) - defer file.Close() + defer func() { + _ = file.Close() + }() err = format.Parse(file, func(request *types.RequestResponse) bool { gotMethodsToURLs = append(gotMethodsToURLs, request.URL.String()) diff --git a/pkg/input/formats/formats.go b/pkg/input/formats/formats.go index 03c65d3fe..a680888ae 100644 --- a/pkg/input/formats/formats.go +++ b/pkg/input/formats/formats.go @@ -88,7 +88,9 @@ func WriteOpenAPIVarDumpFile(vars *OpenAPIParamsCfgFile) error { if err != nil { return err } - defer f.Close() + defer func() { + _ = f.Close() + }() bin, err := yaml.Marshal(vars) if err != nil { return err diff --git a/pkg/input/formats/json/json_test.go b/pkg/input/formats/json/json_test.go index a6734f083..830385e21 100644 --- a/pkg/input/formats/json/json_test.go +++ b/pkg/input/formats/json/json_test.go @@ -44,7 +44,9 @@ func TestJSONFormatterParse(t *testing.T) { file, err := os.Open(proxifyInputFile) require.Nilf(t, err, "error opening proxify input file: %v", err) - defer file.Close() + defer func() { + _ = file.Close() + }() var urls []string err = format.Parse(file, func(request *types.RequestResponse) bool { diff --git a/pkg/input/formats/openapi/generator.go b/pkg/input/formats/openapi/generator.go index 1906858cb..30778d8dc 100644 --- a/pkg/input/formats/openapi/generator.go +++ b/pkg/input/formats/openapi/generator.go @@ -217,7 +217,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error { return nil } else { // if it is in path then remove it from path - opts.requestPath = strings.Replace(opts.requestPath, fmt.Sprintf("{%s}", value.Name), "", -1) + opts.requestPath = strings.ReplaceAll(opts.requestPath, fmt.Sprintf("{%s}", value.Name), "") if !opts.opts.RequiredOnly { gologger.Verbose().Msgf("openapi: skipping optional param (%s) in (%v) in request [%s] %s due to missing value (%v)\n", value.Name, value.In, opts.method, opts.requestPath, value.Name) } @@ -233,7 +233,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error { return nil } else { // if it is in path then remove it from path - opts.requestPath = strings.Replace(opts.requestPath, fmt.Sprintf("{%s}", value.Name), "", -1) + opts.requestPath = strings.ReplaceAll(opts.requestPath, fmt.Sprintf("{%s}", value.Name), "") if !opts.opts.RequiredOnly { gologger.Verbose().Msgf("openapi: skipping optional param (%s) in (%v) in request [%s] %s due to missing value (%v)\n", value.Name, value.In, opts.method, opts.requestPath, value.Name) } @@ -244,7 +244,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error { } if opts.requiredOnly && !value.Required { // remove them from path if any - opts.requestPath = strings.Replace(opts.requestPath, fmt.Sprintf("{%s}", value.Name), "", -1) + opts.requestPath = strings.ReplaceAll(opts.requestPath, fmt.Sprintf("{%s}", value.Name), "") continue // Skip this parameter if it is not required and we want only required ones } @@ -327,7 +327,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error { _ = multipartWriter.WriteField(k, types.ToString(v)) } } - multipartWriter.Close() + _ = multipartWriter.Close() // body = buffer.String() cloned.Body = io.NopCloser(buffer) cloned.ContentLength = int64(len(buffer.Bytes())) diff --git a/pkg/input/formats/openapi/openapi_test.go b/pkg/input/formats/openapi/openapi_test.go index c202bdcbe..4f6b429e0 100644 --- a/pkg/input/formats/openapi/openapi_test.go +++ b/pkg/input/formats/openapi/openapi_test.go @@ -44,7 +44,9 @@ func TestOpenAPIParser(t *testing.T) { file, err := os.Open(proxifyInputFile) require.Nilf(t, err, "error opening proxify input file: %v", err) - defer file.Close() + defer func() { + _ = file.Close() + }() err = format.Parse(file, func(rr *types.RequestResponse) bool { gotMethodsToURLs[rr.Request.Method] = append(gotMethodsToURLs[rr.Request.Method], diff --git a/pkg/input/formats/swagger/swagger_test.go b/pkg/input/formats/swagger/swagger_test.go index caed82a13..c354e1a60 100644 --- a/pkg/input/formats/swagger/swagger_test.go +++ b/pkg/input/formats/swagger/swagger_test.go @@ -17,7 +17,9 @@ func TestSwaggerAPIParser(t *testing.T) { file, err := os.Open(proxifyInputFile) require.Nilf(t, err, "error opening proxify input file: %v", err) - defer file.Close() + defer func() { + _ = file.Close() + }() err = format.Parse(file, func(request *types.RequestResponse) bool { gotMethodsToURLs = append(gotMethodsToURLs, request.URL.String()) diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go index 0b91e774a..efc7733ea 100644 --- a/pkg/input/formats/yaml/multidoc_test.go +++ b/pkg/input/formats/yaml/multidoc_test.go @@ -20,7 +20,9 @@ func TestYamlFormatterParse(t *testing.T) { file, err := os.Open(proxifyInputFile) require.Nilf(t, err, "error opening proxify input file: %v", err) - defer file.Close() + defer func() { + _ = file.Close() + }() var urls []string err = format.Parse(file, func(request *types.RequestResponse) bool { diff --git a/pkg/input/provider/http/multiformat.go b/pkg/input/provider/http/multiformat.go index a534879c1..a2440c36d 100644 --- a/pkg/input/provider/http/multiformat.go +++ b/pkg/input/provider/http/multiformat.go @@ -73,7 +73,7 @@ func NewHttpInputProvider(opts *HttpMultiFormatOptions) (*HttpInputProvider, err } defer func() { if inputFile != nil { - inputFile.Close() + _ = inputFile.Close() } }() diff --git a/pkg/input/provider/list/hmap.go b/pkg/input/provider/list/hmap.go index 6f41920cd..a08e909e1 100644 --- a/pkg/input/provider/list/hmap.go +++ b/pkg/input/provider/list/hmap.go @@ -258,7 +258,7 @@ func (i *ListInputProvider) InputType() string { // Close closes the input provider func (i *ListInputProvider) Close() { - i.hostMap.Close() + _ = i.hostMap.Close() if i.hostMapStream != nil { i.hostMapStream.Close() } @@ -298,7 +298,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error { } if input != nil { i.scanInputFromReader(input) - input.Close() + _ = input.Close() } } if options.Uncover && options.UncoverQuery != nil { diff --git a/pkg/input/transform_test.go b/pkg/input/transform_test.go index 699d87772..4cd866562 100644 --- a/pkg/input/transform_test.go +++ b/pkg/input/transform_test.go @@ -13,7 +13,9 @@ func TestConvertInputToType(t *testing.T) { hm, err := hybrid.New(hybrid.DefaultDiskOptions) require.NoError(t, err, "could not create hybrid map") helper.InputsHTTP = hm - defer hm.Close() + defer func() { + _ = hm.Close() + }() _ = hm.Set("google.com", []byte("https://google.com")) diff --git a/pkg/installer/template_test.go b/pkg/installer/template_test.go index 0f277db65..952c44596 100644 --- a/pkg/installer/template_test.go +++ b/pkg/installer/template_test.go @@ -18,10 +18,12 @@ func TestTemplateInstallation(t *testing.T) { tm := &TemplateManager{} dir, err := os.MkdirTemp("", "nuclei-templates-*") require.Nil(t, err) - defer os.RemoveAll(dir) cfgdir, err := os.MkdirTemp("", "nuclei-config-*") require.Nil(t, err) - defer os.RemoveAll(cfgdir) + defer func() { + _ = os.RemoveAll(dir) + _ = os.RemoveAll(cfgdir) + }() // set the config directory to a temporary directory config.DefaultConfig.SetConfigDir(cfgdir) diff --git a/pkg/installer/versioncheck.go b/pkg/installer/versioncheck.go index ffddd9363..f7764c731 100644 --- a/pkg/installer/versioncheck.go +++ b/pkg/installer/versioncheck.go @@ -92,7 +92,9 @@ func doVersionCheck(isSDK bool) error { if err != nil { return err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() bin, err := io.ReadAll(resp.Body) if err != nil { return err diff --git a/pkg/installer/zipslip_unix_test.go b/pkg/installer/zipslip_unix_test.go index 7e9eab94a..82323d8e8 100644 --- a/pkg/installer/zipslip_unix_test.go +++ b/pkg/installer/zipslip_unix_test.go @@ -47,7 +47,9 @@ func TestZipSlip(t *testing.T) { } configuredTemplateDirectory := filepath.Join(os.TempDir(), "templates") - defer os.RemoveAll(configuredTemplateDirectory) + defer func() { + _ = os.RemoveAll(configuredTemplateDirectory) + }() t.Run("negative scenarios", func(t *testing.T) { filePathsFromZip := []string{ diff --git a/pkg/js/devtools/bindgen/output.go b/pkg/js/devtools/bindgen/output.go index 990d1fa43..db12d24c3 100644 --- a/pkg/js/devtools/bindgen/output.go +++ b/pkg/js/devtools/bindgen/output.go @@ -36,10 +36,10 @@ func (d *TemplateData) WriteGoTemplate(outputDirectory string, pkgName string) e } if err := tmpl.Execute(output, d); err != nil { - output.Close() + _ = output.Close() return errors.Wrap(err, "could not execute go class template") } - output.Close() + _ = output.Close() cmd := exec.Command("gofmt", "-w", filename) cmd.Stderr = os.Stderr @@ -68,10 +68,10 @@ func (d *TemplateData) WriteJSTemplate(outputDirectory string, pkgName string) e } if err := tmpl.Execute(output, d); err != nil { - output.Close() + _ = output.Close() return errors.Wrap(err, "could not execute js class template") } - output.Close() + _ = output.Close() cmd := exec.Command("js-beautify", "-r", filename) cmd.Stderr = os.Stderr @@ -91,18 +91,20 @@ func (d *TemplateData) WriteMarkdownIndexTemplate(outputDirectory string) error if err != nil { return errors.Wrap(err, "could not create markdown index template") } - defer output.Close() + defer func() { + _ = output.Close() + }() buffer := &bytes.Buffer{} _, _ = buffer.WriteString("# Index\n\n") for _, v := range markdownIndexes { - _, _ = buffer.WriteString(fmt.Sprintf("* %s\n", v)) + _, _ = fmt.Fprintf(buffer, "* %s\n", v) } _, _ = buffer.WriteString("\n\n") _, _ = buffer.WriteString("# Scripts\n\n") for _, v := range d.NativeScripts { - _, _ = buffer.WriteString(fmt.Sprintf("* `%s`\n", v)) + _, _ = fmt.Fprintf(buffer, "* `%s`\n", v) } if _, err := output.Write(buffer.Bytes()); err != nil { return errors.Wrap(err, "could not write markdown index template") @@ -131,10 +133,10 @@ func (d *TemplateData) WriteMarkdownLibraryDocumentation(outputDirectory string, markdownIndexes[pkgName] = fmt.Sprintf("[%s](%s.md)", pkgName, pkgName) if err := tmpl.Execute(output, d); err != nil { - output.Close() + _ = output.Close() return err } - output.Close() + _ = output.Close() return nil } diff --git a/pkg/js/libs/kerberos/sendtokdc.go b/pkg/js/libs/kerberos/sendtokdc.go index 7e14386a7..0cb3f47e1 100644 --- a/pkg/js/libs/kerberos/sendtokdc.go +++ b/pkg/js/libs/kerberos/sendtokdc.go @@ -80,7 +80,9 @@ func sendToKDCTcp(kclient *Client, msg string) ([]byte, error) { errs = append(errs, fmt.Sprintf("error establishing connection to %s: %v", kdcs[i], err)) continue } - defer tcpConn.Close() + defer func() { + _ = tcpConn.Close() + }() _ = tcpConn.SetDeadline(time.Now().Add(time.Duration(kclient.config.timeout) * time.Second)) //read and write deadline rb, err := sendTCP(tcpConn.(*net.TCPConn), []byte(msg)) if err != nil { @@ -113,7 +115,9 @@ func sendToKDCUdp(kclient *Client, msg string) ([]byte, error) { errs = append(errs, fmt.Sprintf("error establishing connection to %s: %v", kdcs[i], err)) continue } - defer udpConn.Close() + defer func() { + _ = udpConn.Close() + }() _ = udpConn.SetDeadline(time.Now().Add(time.Duration(kclient.config.timeout) * time.Second)) //read and write deadline rb, err := sendUDP(udpConn.(*net.UDPConn), []byte(msg)) if err != nil { @@ -132,7 +136,9 @@ func sendToKDCUdp(kclient *Client, msg string) ([]byte, error) { // sendUDP sends bytes to connection over UDP. func sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) { var r []byte - defer conn.Close() + defer func() { + _ = conn.Close() + }() _, err := conn.Write(b) if err != nil { return r, fmt.Errorf("error sending to (%s): %v", conn.RemoteAddr().String(), err) @@ -151,7 +157,9 @@ func sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) { // sendTCP sends bytes to connection over TCP. func sendTCP(conn *net.TCPConn, b []byte) ([]byte, error) { - defer conn.Close() + defer func() { + _ = conn.Close() + }() var r []byte // RFC 4120 7.2.2 specifies the first 4 bytes indicate the length of the message in big endian order. hb := make([]byte, 4) diff --git a/pkg/js/libs/ldap/ldap.go b/pkg/js/libs/ldap/ldap.go index 463f86b6a..8e9e4eec5 100644 --- a/pkg/js/libs/ldap/ldap.go +++ b/pkg/js/libs/ldap/ldap.go @@ -331,7 +331,7 @@ func (c *Client) CollectMetadata() Metadata { // ``` func (c *Client) GetVersion() []string { c.nj.Require(c.conn != nil, "no existing connection") - + // Query root DSE for supported LDAP versions sr := ldap.NewSearchRequest( "", @@ -341,18 +341,17 @@ func (c *Client) GetVersion() []string { "(objectClass=*)", []string{"supportedLDAPVersion"}, nil) - + res, err := c.conn.Search(sr) c.nj.HandleError(err, "failed to get LDAP version") - + if len(res.Entries) > 0 { return res.Entries[0].GetAttributeValues("supportedLDAPVersion") } - + return []string{"unknown"} } - // close the ldap connection // @example // ```javascript @@ -361,5 +360,5 @@ func (c *Client) GetVersion() []string { // client.Close(); // ``` func (c *Client) Close() { - c.conn.Close() + _ = c.conn.Close() } diff --git a/pkg/js/libs/mssql/mssql.go b/pkg/js/libs/mssql/mssql.go index 938318a85..2e986e946 100644 --- a/pkg/js/libs/mssql/mssql.go +++ b/pkg/js/libs/mssql/mssql.go @@ -76,7 +76,9 @@ func connect(host string, port int, username string, password string, dbName str if err != nil { return false, err } - defer db.Close() + defer func() { + _ = db.Close() + }() _, err = db.Exec("select 1") if err != nil { @@ -120,7 +122,9 @@ func isMssql(host string, port int) (bool, error) { if err != nil { return false, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() data, check, err := mssql.DetectMSSQL(conn, 5*time.Second) if check && err != nil { @@ -172,7 +176,9 @@ func (c *MSSQLClient) ExecuteQuery(host string, port int, username, password, db if err != nil { return nil, err } - defer db.Close() + defer func() { + _ = db.Close() + }() db.SetMaxOpenConns(1) db.SetMaxIdleConns(0) diff --git a/pkg/js/libs/mysql/mysql.go b/pkg/js/libs/mysql/mysql.go index 456605926..214a76901 100644 --- a/pkg/js/libs/mysql/mysql.go +++ b/pkg/js/libs/mysql/mysql.go @@ -50,7 +50,9 @@ func isMySQL(host string, port int) (bool, error) { if err != nil { return false, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() plugin := &mysqlplugin.MYSQLPlugin{} service, err := plugin.Run(conn, 5*time.Second, plugins.Target{Host: host}) @@ -140,7 +142,9 @@ func fingerprintMySQL(host string, port int) (MySQLInfo, error) { if err != nil { return info, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() plugin := &mysqlplugin.MYSQLPlugin{} service, err := plugin.Run(conn, 5*time.Second, plugins.Target{Host: host}) @@ -212,7 +216,9 @@ func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*ut if err != nil { return nil, err } - defer db.Close() + defer func() { + _ = db.Close() + }() db.SetMaxOpenConns(1) db.SetMaxIdleConns(0) diff --git a/pkg/js/libs/mysql/mysql_private.go b/pkg/js/libs/mysql/mysql_private.go index c5f229217..7a5edebc1 100644 --- a/pkg/js/libs/mysql/mysql_private.go +++ b/pkg/js/libs/mysql/mysql_private.go @@ -77,7 +77,9 @@ func connectWithDSN(dsn string) (bool, error) { if err != nil { return false, err } - defer db.Close() + defer func() { + _ = db.Close() + }() db.SetMaxOpenConns(1) db.SetMaxIdleConns(0) diff --git a/pkg/js/libs/oracle/oracle.go b/pkg/js/libs/oracle/oracle.go index 9e4326421..ed8193fd9 100644 --- a/pkg/js/libs/oracle/oracle.go +++ b/pkg/js/libs/oracle/oracle.go @@ -45,7 +45,9 @@ func isOracle(host string, port int) (IsOracleResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() oracledbPlugin := oracledb.ORACLEPlugin{} service, err := oracledbPlugin.Run(conn, timeout, plugins.Target{Host: host}) diff --git a/pkg/js/libs/pop3/pop3.go b/pkg/js/libs/pop3/pop3.go index 2662befd4..5b236a612 100644 --- a/pkg/js/libs/pop3/pop3.go +++ b/pkg/js/libs/pop3/pop3.go @@ -46,7 +46,9 @@ func isPoP3(host string, port int) (IsPOP3Response, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() pop3Plugin := pop3.POP3Plugin{} service, err := pop3Plugin.Run(conn, timeout, plugins.Target{Host: host}) diff --git a/pkg/js/libs/postgres/postgres.go b/pkg/js/libs/postgres/postgres.go index e3093c49d..d8b76e8e5 100644 --- a/pkg/js/libs/postgres/postgres.go +++ b/pkg/js/libs/postgres/postgres.go @@ -12,8 +12,8 @@ import ( "github.com/praetorian-inc/fingerprintx/pkg/plugins" postgres "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/postgresql" utils "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" - "github.com/projectdiscovery/nuclei/v3/pkg/js/utils/pgwrap" - _ "github.com/projectdiscovery/nuclei/v3/pkg/js/utils/pgwrap" + "github.com/projectdiscovery/nuclei/v3/pkg/js/utils/pgwrap" //nolint:staticcheck // need to call init + _ "github.com/projectdiscovery/nuclei/v3/pkg/js/utils/pgwrap" //nolint:staticcheck "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) @@ -49,7 +49,9 @@ func isPostgres(host string, port int) (bool, error) { if err != nil { return false, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() _ = conn.SetDeadline(time.Now().Add(timeout)) @@ -121,7 +123,9 @@ func executeQuery(host string, port int, username string, password string, dbNam if err != nil { return nil, err } - defer db.Close() + defer func() { + _ = db.Close() + }() rows, err := db.Query(query) if err != nil { @@ -182,7 +186,9 @@ func connect(host string, port int, username string, password string, dbName str }, IdleCheckFrequency: -1, }).WithContext(ctx).WithTimeout(10 * time.Second) - defer db.Close() + defer func() { + _ = db.Close() + }() _, err := db.Exec("select 1") if err != nil { diff --git a/pkg/js/libs/rdp/rdp.go b/pkg/js/libs/rdp/rdp.go index 7a985ab25..e2a7996b3 100644 --- a/pkg/js/libs/rdp/rdp.go +++ b/pkg/js/libs/rdp/rdp.go @@ -48,7 +48,9 @@ func isRDP(host string, port int) (IsRDPResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() server, isRDP, err := rdp.DetectRDP(conn, timeout) if err != nil { @@ -99,7 +101,9 @@ func checkRDPAuth(host string, port int) (CheckRDPAuthResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() pluginInfo, auth, err := rdp.DetectRDPAuth(conn, timeout) if err != nil { diff --git a/pkg/js/libs/redis/redis.go b/pkg/js/libs/redis/redis.go index 3fb4de83a..bf1f61644 100644 --- a/pkg/js/libs/redis/redis.go +++ b/pkg/js/libs/redis/redis.go @@ -34,7 +34,9 @@ func getServerInfo(host string, port int) (string, error) { Password: "", // no password set DB: 0, // use default DB }) - defer client.Close() + defer func() { + _ = client.Close() + }() // Ping the Redis server _, err := client.Ping(context.TODO()).Result() @@ -73,7 +75,9 @@ func connect(host string, port int, password string) (bool, error) { Password: password, // no password set DB: 0, // use default DB }) - defer client.Close() + defer func() { + _ = client.Close() + }() _, err := client.Ping(context.TODO()).Result() if err != nil { @@ -110,7 +114,9 @@ func getServerInfoAuth(host string, port int, password string) (string, error) { Password: password, // no password set DB: 0, // use default DB }) - defer client.Close() + defer func() { + _ = client.Close() + }() // Ping the Redis server _, err := client.Ping(context.TODO()).Result() @@ -145,7 +151,9 @@ func isAuthenticated(host string, port int) (bool, error) { if err != nil { return false, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() _, err = plugin.Run(conn, timeout, plugins.Target{Host: host}) if err != nil { @@ -171,7 +179,9 @@ func RunLuaScript(host string, port int, password string, script string) (interf Password: password, DB: 0, // use default DB }) - defer client.Close() + defer func() { + _ = client.Close() + }() // Ping the Redis server _, err := client.Ping(context.TODO()).Result() diff --git a/pkg/js/libs/rsync/rsync.go b/pkg/js/libs/rsync/rsync.go index c9cf18f37..41ff2e5fd 100644 --- a/pkg/js/libs/rsync/rsync.go +++ b/pkg/js/libs/rsync/rsync.go @@ -46,7 +46,9 @@ func isRsync(host string, port int) (IsRsyncResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() rsyncPlugin := rsync.RSYNCPlugin{} service, err := rsyncPlugin.Run(conn, timeout, plugins.Target{Host: host}) diff --git a/pkg/js/libs/smb/smb.go b/pkg/js/libs/smb/smb.go index 2d9812814..4309b6e42 100644 --- a/pkg/js/libs/smb/smb.go +++ b/pkg/js/libs/smb/smb.go @@ -60,7 +60,9 @@ func connectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { if err != nil { return nil, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() result, err = getSMBInfo(conn, true, true) if err != nil { return result, nil @@ -116,7 +118,9 @@ func listShares(host string, port int, user string, password string) ([]string, if err != nil { return nil, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() d := &smb2.Dialer{ Initiator: &smb2.NTLMInitiator{ diff --git a/pkg/js/libs/smb/smb_private.go b/pkg/js/libs/smb/smb_private.go index 74f076b12..a9d655ce1 100644 --- a/pkg/js/libs/smb/smb_private.go +++ b/pkg/js/libs/smb/smb_private.go @@ -24,7 +24,9 @@ func collectSMBv2Metadata(host string, port int, timeout time.Duration) (*plugin if err != nil { return nil, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() metadata, err := smb.DetectSMBv2(conn, timeout) if err != nil { diff --git a/pkg/js/libs/smb/smbghost.go b/pkg/js/libs/smb/smbghost.go index 6c8b3c27c..8f973e096 100644 --- a/pkg/js/libs/smb/smbghost.go +++ b/pkg/js/libs/smb/smbghost.go @@ -41,7 +41,9 @@ func detectSMBGhost(host string, port int) (bool, error) { return false, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() _, err = conn.Write([]byte(pkt)) if err != nil { diff --git a/pkg/js/libs/smtp/smtp.go b/pkg/js/libs/smtp/smtp.go index 7fe9076e2..c4856227d 100644 --- a/pkg/js/libs/smtp/smtp.go +++ b/pkg/js/libs/smtp/smtp.go @@ -90,7 +90,9 @@ func (c *Client) IsSMTP() (SMTPResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() smtpPlugin := pluginsmtp.SMTPPlugin{} service, err := smtpPlugin.Run(conn, timeout, plugins.Target{Host: c.host}) @@ -126,7 +128,9 @@ func (c *Client) IsOpenRelay(msg *SMTPMessage) (bool, error) { if err != nil { return false, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() client, err := smtp.NewClient(conn, c.host) if err != nil { return false, err diff --git a/pkg/js/libs/ssh/ssh.go b/pkg/js/libs/ssh/ssh.go index f6639a57b..32cd870fc 100644 --- a/pkg/js/libs/ssh/ssh.go +++ b/pkg/js/libs/ssh/ssh.go @@ -128,7 +128,9 @@ func (c *SSHClient) Run(cmd string) (string, error) { if err != nil { return "", err } - defer session.Close() + defer func() { + _ = session.Close() + }() data, err := session.Output(cmd) if err != nil { @@ -203,7 +205,9 @@ func connectSSHInfoMode(opts *connectOptions) (*ssh.HandshakeLog, error) { if err != nil { return nil, err } - defer client.Close() + defer func() { + _ = client.Close() + }() return data, nil } diff --git a/pkg/js/libs/telnet/telnet.go b/pkg/js/libs/telnet/telnet.go index d71454754..d585b2af7 100644 --- a/pkg/js/libs/telnet/telnet.go +++ b/pkg/js/libs/telnet/telnet.go @@ -46,7 +46,9 @@ func isTelnet(host string, port int) (IsTelnetResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() telnetPlugin := telnet.TELNETPlugin{} service, err := telnetPlugin.Run(conn, timeout, plugins.Target{Host: host}) diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index c5d4577c0..a3d72499c 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -47,7 +47,9 @@ func isVNC(host string, port int) (IsVNCResponse, error) { if err != nil { return resp, err } - defer conn.Close() + defer func() { + _ = conn.Close() + }() vncPlugin := vnc.VNCPlugin{} service, err := vncPlugin.Run(conn, timeout, plugins.Target{Host: host}) diff --git a/pkg/js/utils/util.go b/pkg/js/utils/util.go index df08fb414..4a49b3879 100644 --- a/pkg/js/utils/util.go +++ b/pkg/js/utils/util.go @@ -21,7 +21,9 @@ type SQLResult struct { // // The function closes the sql.Rows when finished. func UnmarshalSQLRows(rows *sql.Rows) (*SQLResult, error) { - defer rows.Close() + defer func() { + _ = rows.Close() + }() columnTypes, err := rows.ColumnTypes() if err != nil { return nil, err diff --git a/pkg/operators/operators.go b/pkg/operators/operators.go index 50fabfc78..1fb1ab1c5 100644 --- a/pkg/operators/operators.go +++ b/pkg/operators/operators.go @@ -243,7 +243,7 @@ func (operators *Operators) Execute(data map[string]interface{}, match MatchFunc } // state variable to check if all extractors are internal - var allInternalExtractors bool = true + var allInternalExtractors = true // Start with the extractors first and evaluate them. for _, extractor := range operators.Extractors { diff --git a/pkg/output/output.go b/pkg/output/output.go index 02b62f6e1..571bff782 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -229,10 +229,8 @@ type IssueTrackerMetadata struct { // NewStandardWriter creates a new output writer based on user configurations func NewStandardWriter(options *types.Options) (*StandardWriter, error) { - resumeBool := false - if options.Resume != "" { - resumeBool = true - } + resumeBool := options.Resume != "" + auroraColorizer := aurora.NewAurora(!options.NoColor) var outputFile io.WriteCloser @@ -452,13 +450,13 @@ func (w *StandardWriter) Colorizer() aurora.Aurora { // Close closes the output writing interface func (w *StandardWriter) Close() { if w.outputFile != nil { - w.outputFile.Close() + _ = w.outputFile.Close() } if w.traceFile != nil { - w.traceFile.Close() + _ = w.traceFile.Close() } if w.errorFile != nil { - w.errorFile.Close() + _ = w.errorFile.Close() } } @@ -563,8 +561,8 @@ func (w *StandardWriter) WriteStoreDebugData(host, templateID, eventType string, gologger.Error().Msgf("Could not open debug output file: %s", err) return } - _, _ = f.WriteString(fmt.Sprintln(data)) - f.Close() + _, _ = fmt.Fprintln(f, data) + _ = f.Close() } } diff --git a/pkg/progress/progress.go b/pkg/progress/progress.go index 853fb103d..ac62cffd3 100644 --- a/pkg/progress/progress.go +++ b/pkg/progress/progress.go @@ -148,7 +148,7 @@ func (p *StatsTicker) makePrintCallback() func(stats clistats.StatisticsClient) if startedAt, ok := stats.GetStatic("startedAt"); ok { if startedAtTime, ok := startedAt.(time.Time); ok { duration = time.Since(startedAtTime) - builder.WriteString(fmt.Sprintf("[%s]", fmtDuration(duration))) + _, _ = fmt.Fprintf(builder, "[%s]", fmtDuration(duration)) } } @@ -203,7 +203,7 @@ func (p *StatsTicker) makePrintCallback() func(stats clistats.StatisticsClient) builder.WriteRune('\n') } - fmt.Fprintf(os.Stderr, "%s", builder.String()) + _, _ = fmt.Fprintf(os.Stderr, "%s", builder.String()) return builder.String() } } @@ -211,7 +211,7 @@ func (p *StatsTicker) makePrintCallback() func(stats clistats.StatisticsClient) func printCallbackJSON(stats clistats.StatisticsClient) interface{} { builder := &strings.Builder{} if err := json.NewEncoder(builder).Encode(metricsMap(stats)); err == nil { - fmt.Fprintf(os.Stderr, "%s", builder.String()) + _, _ = fmt.Fprintf(os.Stderr, "%s", builder.String()) } return builder.String() } diff --git a/pkg/projectfile/project.go b/pkg/projectfile/project.go index 84e0a0cb5..9a79c4aa8 100644 --- a/pkg/projectfile/project.go +++ b/pkg/projectfile/project.go @@ -84,5 +84,5 @@ func (pf *ProjectFile) Set(req []byte, resp *http.Response, data []byte) error { } func (pf *ProjectFile) Close() { - pf.hm.Close() + _ = pf.hm.Close() } diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index 1d687d235..ad1c0b234 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -248,14 +248,14 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa gologger.Debug().MsgFunc(func() string { dashes := strings.Repeat("-", 15) sb := &strings.Builder{} - sb.WriteString(fmt.Sprintf("[%s] Dumped Executed Source Code for input/stdin: '%v'", request.options.TemplateID, input.MetaInput.Input)) - sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Source Code:", dashes)) + fmt.Fprintf(sb, "[%s] Dumped Executed Source Code for input/stdin: '%v'", request.options.TemplateID, input.MetaInput.Input) + fmt.Fprintf(sb, "\n%v\n%v\n%v\n", dashes, "Source Code:", dashes) sb.WriteString(interpretEnvVars(request.Source, allvars)) sb.WriteString("\n") - sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Command Executed:", dashes)) + fmt.Fprintf(sb, "\n%v\n%v\n%v\n", dashes, "Command Executed:", dashes) sb.WriteString(interpretEnvVars(gOutput.Command, allvars)) sb.WriteString("\n") - sb.WriteString(fmt.Sprintf("\n%v\n%v\n%v\n", dashes, "Command Output:", dashes)) + fmt.Fprintf(sb, "\n%v\n%v\n%v\n", dashes, "Command Output:", dashes) sb.WriteString(gOutput.DebugData.String()) sb.WriteString("\n") sb.WriteString("[WRN] Command Output here is stdout+sterr, in response variables they are seperate (use -v -svd flags for more details)") diff --git a/pkg/protocols/common/automaticscan/automaticscan.go b/pkg/protocols/common/automaticscan/automaticscan.go index a5e51c177..00ed60e69 100644 --- a/pkg/protocols/common/automaticscan/automaticscan.go +++ b/pkg/protocols/common/automaticscan/automaticscan.go @@ -77,7 +77,7 @@ func New(opts Options) (*Service, error) { mappingFile := filepath.Join(config.DefaultConfig.GetTemplateDir(), mappingFilename) if file, err := os.Open(mappingFile); err == nil { _ = yaml.NewDecoder(file).Decode(&mappingData) - file.Close() + _ = file.Close() } if opts.ExecuterOpts.Options.Verbose { gologger.Verbose().Msgf("Normalized mapping (%d): %v\n", len(mappingData), mappingData) @@ -206,7 +206,9 @@ func (s *Service) getTagsUsingWappalyzer(input *contextargs.MetaInput) []string if err != nil { return nil } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() data, err := io.ReadAll(io.LimitReader(resp.Body, maxDefaultBody)) if err != nil { return nil diff --git a/pkg/protocols/common/expressions/expressions.go b/pkg/protocols/common/expressions/expressions.go index a3681e358..bd04cabf1 100644 --- a/pkg/protocols/common/expressions/expressions.go +++ b/pkg/protocols/common/expressions/expressions.go @@ -76,11 +76,9 @@ func FindExpressions(data, OpenMarker, CloseMarker string, base map[string]inter iterations int exps []string ) - for { + for iterations <= maxIterations { // check if we reached the maximum number of iterations - if iterations > maxIterations { - break - } + iterations++ // attempt to find open markers indexOpenMarker := strings.Index(data, OpenMarker) diff --git a/pkg/protocols/common/generators/load.go b/pkg/protocols/common/generators/load.go index 1d46233f2..892fe358a 100644 --- a/pkg/protocols/common/generators/load.go +++ b/pkg/protocols/common/generators/load.go @@ -42,7 +42,9 @@ func (generator *PayloadGenerator) loadPayloads(payloads map[string]interface{}, // loadPayloadsFromFile loads a file to a string slice func (generator *PayloadGenerator) loadPayloadsFromFile(file io.ReadCloser) ([]string, error) { var lines []string - defer file.Close() + defer func() { + _ = file.Close() + }() scanner := bufio.NewScanner(file) for scanner.Scan() { diff --git a/pkg/protocols/common/hosterrorscache/hosterrorscache.go b/pkg/protocols/common/hosterrorscache/hosterrorscache.go index 3039dbdf0..3053b8efb 100644 --- a/pkg/protocols/common/hosterrorscache/hosterrorscache.go +++ b/pkg/protocols/common/hosterrorscache/hosterrorscache.go @@ -9,7 +9,7 @@ import ( "sync" "sync/atomic" - "github.com/Mzack9999/gcache" + "github.com/projectdiscovery/gcache" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs" @@ -85,7 +85,7 @@ func (c *Cache) Close() { // NormalizeCacheValue processes the input value and returns a normalized cache // value. func (c *Cache) NormalizeCacheValue(value string) string { - var normalizedValue string = value + var normalizedValue = value u, err := url.ParseRequestURI(value) if err != nil || u.Host == "" { diff --git a/pkg/protocols/common/interactsh/interactsh.go b/pkg/protocols/common/interactsh/interactsh.go index da59f10fb..6bb70709f 100644 --- a/pkg/protocols/common/interactsh/interactsh.go +++ b/pkg/protocols/common/interactsh/interactsh.go @@ -183,9 +183,9 @@ func (c *Client) processInteractionForRequest(interaction *server.Interaction, d if c.options.FuzzParamsFrequency != nil { if !matched { - c.options.FuzzParamsFrequency.MarkParameter(data.Parameter, data.Request.URL.String(), data.Operators.TemplateID) + c.options.FuzzParamsFrequency.MarkParameter(data.Parameter, data.Request.String(), data.Operators.TemplateID) } else { - c.options.FuzzParamsFrequency.UnmarkParameter(data.Parameter, data.Request.URL.String(), data.Operators.TemplateID) + c.options.FuzzParamsFrequency.UnmarkParameter(data.Parameter, data.Request.String(), data.Operators.TemplateID) } } @@ -257,7 +257,7 @@ func (c *Client) Close() bool { } if c.interactsh != nil { _ = c.interactsh.StopPolling() - c.interactsh.Close() + _ = c.interactsh.Close() } c.requests.Purge() @@ -424,7 +424,7 @@ func (c *Client) debugPrintInteraction(interaction *server.Interaction, event *o builder.WriteString(formatInteractionMessage("LDAP Interaction", interaction.RawRequest, event, c.options.NoColor)) } } - fmt.Fprint(os.Stderr, builder.String()) + _, _ = fmt.Fprint(os.Stderr, builder.String()) } func formatInteractionHeader(protocol, ID, address string, at time.Time) string { diff --git a/pkg/protocols/common/randomip/randomip.go b/pkg/protocols/common/randomip/randomip.go index 8c9321980..ed035485d 100644 --- a/pkg/protocols/common/randomip/randomip.go +++ b/pkg/protocols/common/randomip/randomip.go @@ -35,7 +35,7 @@ func GetRandomIPWithCidr(cidrs ...string) (net.IP, error) { } switch { - case 255 == ipnet.Mask[len(ipnet.Mask)-1]: + case ipnet.Mask[len(ipnet.Mask)-1] == 255: return baseIp, nil case iputil.IsIPv4(baseIp.String()): return getRandomIP(ipnet, 4), nil diff --git a/pkg/protocols/dns/cluster.go b/pkg/protocols/dns/cluster.go index 86852b4d7..efa021032 100644 --- a/pkg/protocols/dns/cluster.go +++ b/pkg/protocols/dns/cluster.go @@ -6,7 +6,6 @@ import ( "github.com/cespare/xxhash" ) - // TmplClusterKey generates a unique key for the request // to be used in the clustering process. func (request *Request) TmplClusterKey() uint64 { @@ -20,5 +19,5 @@ func (request *Request) TmplClusterKey() uint64 { // IsClusterable returns true if the request is eligible to be clustered. func (request *Request) IsClusterable() bool { - return !(len(request.Resolvers) > 0 || request.Trace || request.ID != "") + return len(request.Resolvers) <= 0 && !request.Trace && request.ID == "" } diff --git a/pkg/protocols/dns/dnsclientpool/clientpool.go b/pkg/protocols/dns/dnsclientpool/clientpool.go index 8eb19b8ba..c1805be1c 100644 --- a/pkg/protocols/dns/dnsclientpool/clientpool.go +++ b/pkg/protocols/dns/dnsclientpool/clientpool.go @@ -70,7 +70,7 @@ func (c *Configuration) Hash() string { // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration) (*retryabledns.Client, error) { - if !(configuration.Retries > 1) && len(configuration.Resolvers) == 0 { + if (configuration.Retries <= 1) && len(configuration.Resolvers) == 0 { return normalClient, nil } hash := configuration.Hash() diff --git a/pkg/protocols/dns/operators.go b/pkg/protocols/dns/operators.go index 0f1831530..7830edfc8 100644 --- a/pkg/protocols/dns/operators.go +++ b/pkg/protocols/dns/operators.go @@ -150,7 +150,7 @@ func traceToString(traceData *retryabledns.TraceData, withSteps bool) string { if traceData != nil { for i, dnsRecord := range traceData.DNSData { if withSteps { - buffer.WriteString(fmt.Sprintf("request %d to resolver %s:\n", i, strings.Join(dnsRecord.Resolver, ","))) + fmt.Fprintf(buffer, "request %d to resolver %s:\n", i, strings.Join(dnsRecord.Resolver, ",")) } buffer.WriteString(dnsRecord.Raw) } diff --git a/pkg/protocols/file/file.go b/pkg/protocols/file/file.go index d9968ffe7..f0e1b0d4f 100644 --- a/pkg/protocols/file/file.go +++ b/pkg/protocols/file/file.go @@ -100,7 +100,7 @@ func (request *Request) GetID() string { // Compile compiles the protocol request for further execution. func (request *Request) Compile(options *protocols.ExecutorOptions) error { // if there are no matchers/extractors, we trigger an error as no operation would be performed on the template - if request.Operators.IsEmpty() { + if request.IsEmpty() { return errors.New("empty operators") } compiled := &request.Operators diff --git a/pkg/protocols/file/find.go b/pkg/protocols/file/find.go index 1ff3227a8..916696f2f 100644 --- a/pkg/protocols/file/find.go +++ b/pkg/protocols/file/find.go @@ -208,7 +208,9 @@ func readChunk(fileName string) ([]byte, error) { return nil, err } - defer r.Close() + defer func() { + _ = r.Close() + }() var buff [1024]byte if _, err = io.ReadFull(r, buff[:]); err != nil { diff --git a/pkg/protocols/file/find_test.go b/pkg/protocols/file/find_test.go index 3df5d2383..43894ae64 100644 --- a/pkg/protocols/file/find_test.go +++ b/pkg/protocols/file/find_test.go @@ -35,7 +35,9 @@ func TestFindInputPaths(t *testing.T) { tempDir, err := os.MkdirTemp("", "test-*") require.Nil(t, err, "could not create temporary directory") - defer os.RemoveAll(tempDir) + defer func() { + _ = os.RemoveAll(tempDir) + }() files := map[string]string{ "test.go": "TEST", diff --git a/pkg/protocols/file/request.go b/pkg/protocols/file/request.go index cd82fc001..e19597ae5 100644 --- a/pkg/protocols/file/request.go +++ b/pkg/protocols/file/request.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "encoding/hex" + "fmt" "io" "os" "path/filepath" @@ -64,7 +65,9 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, gologger.Error().Msgf("%s\n", err) return } - defer fi.Close() + defer func() { + _ = fi.Close() + }() format, stream, _ := archives.Identify(input.Context(), filePath, fi) switch { case format != nil: @@ -82,7 +85,9 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, gologger.Error().Msgf("%s\n", err) return err } - defer reader.Close() + defer func() { + _ = reader.Close() + }() event, fileMatches, err := request.processReader(reader, archiveFileName, input, file.Size(), previous) if err != nil { if errors.Is(err, errEmptyResult) { @@ -123,8 +128,15 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, request.options.Progress.IncrementFailedRequestsBy(1) return } - defer tmpFileOut.Close() - defer os.RemoveAll(tmpFileOut.Name()) + defer func() { + if err := tmpFileOut.Close(); err != nil { + panic(fmt.Errorf("could not close: %+v", err)) + } + + if err := os.Remove(tmpFileOut.Name()); err != nil { + panic(fmt.Errorf("could not remove: %+v", err)) + } + }() _, err = io.Copy(tmpFileOut, reader) if err != nil { gologger.Error().Msgf("%s\n", err) @@ -189,7 +201,9 @@ func (request *Request) processFile(filePath string, input *contextargs.Context, if err != nil { return nil, nil, errors.Errorf("Could not open file path %s: %s\n", filePath, err) } - defer file.Close() + defer func() { + _ = file.Close() + }() stat, err := file.Stat() if err != nil { diff --git a/pkg/protocols/file/request_test.go b/pkg/protocols/file/request_test.go index acb433649..118d1885c 100644 --- a/pkg/protocols/file/request_test.go +++ b/pkg/protocols/file/request_test.go @@ -102,7 +102,9 @@ func TestFileExecuteWithResults(t *testing.T) { tempDir, err := os.MkdirTemp("", "test-*") require.Nil(t, err, "could not create temporary directory") - defer os.RemoveAll(tempDir) + defer func() { + _ = os.RemoveAll(tempDir) + }() files := map[string][]byte{ tt.fileName: tt.data, diff --git a/pkg/protocols/headless/engine/engine.go b/pkg/protocols/headless/engine/engine.go index 0a83eef98..b425f85dd 100644 --- a/pkg/protocols/headless/engine/engine.go +++ b/pkg/protocols/headless/engine/engine.go @@ -140,7 +140,7 @@ func (b *Browser) getHTTPClient() (*http.Client, error) { // Close closes the browser engine func (b *Browser) Close() { - b.engine.Close() + _ = b.engine.Close() b.launcher.Kill() - os.RemoveAll(b.tempDir) + _ = os.RemoveAll(b.tempDir) } diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index 4dca72a6a..519712b21 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -201,7 +201,7 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map if resp, err := http.ReadResponse(bufio.NewReader(strings.NewReader(firstItem.RawResponse)), nil); err == nil { data["header"] = utils.HeadersToString(resp.Header) data["status_code"] = fmt.Sprint(resp.StatusCode) - resp.Body.Close() + _ = resp.Body.Close() } } @@ -216,7 +216,7 @@ func (p *Page) Close() { if p.hijackNative != nil { _ = p.hijackNative.Stop() } - p.page.Close() + _ = p.page.Close() } // Page returns the current page for the actions diff --git a/pkg/protocols/headless/engine/page_actions.go b/pkg/protocols/headless/engine/page_actions.go index 204ce8eea..492b58bb7 100644 --- a/pkg/protocols/headless/engine/page_actions.go +++ b/pkg/protocols/headless/engine/page_actions.go @@ -678,7 +678,7 @@ func (p *Page) WaitPageLifecycleEvent(act *Action, out ActionData, event proto.P // WaitStable waits until the page is stable func (p *Page) WaitStable(act *Action, out ActionData) error { - var dur time.Duration = time.Second // default stable page duration: 1s + var dur = time.Second // default stable page duration: 1s timeout, err := getTimeout(p, act) if err != nil { diff --git a/pkg/protocols/headless/engine/page_actions_test.go b/pkg/protocols/headless/engine/page_actions_test.go index cbd56bb02..04f6d5f49 100644 --- a/pkg/protocols/headless/engine/page_actions_test.go +++ b/pkg/protocols/headless/engine/page_actions_test.go @@ -658,7 +658,9 @@ func testHeadless(t *testing.T, actions []*Action, timeout time.Duration, handle instance, err := browser.NewInstance() require.Nil(t, err, "could not create browser instance") - defer instance.Close() + defer func() { + _ = instance.Close() + }() ts := httptest.NewServer(http.HandlerFunc(handler)) defer ts.Close() @@ -717,7 +719,9 @@ func TestBlockedHeadlessURLS(t *testing.T) { instance, err := browser.NewInstance() require.Nil(t, err, "could not create browser instance") - defer instance.Close() + defer func() { + _ = instance.Close() + }() ts := httptest.NewServer(nil) defer ts.Close() diff --git a/pkg/protocols/headless/request.go b/pkg/protocols/headless/request.go index 83280ee63..afe03c711 100644 --- a/pkg/protocols/headless/request.go +++ b/pkg/protocols/headless/request.go @@ -117,7 +117,9 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p request.options.Progress.IncrementFailedRequestsBy(1) return errors.Wrap(err, errCouldNotGetHtmlElement) } - defer instance.Close() + defer func() { + _ = instance.Close() + }() instance.SetInteractsh(request.options.Interactsh) @@ -159,9 +161,9 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p if act.ActionType.ActionType == engine.ActionNavigate { value := act.GetArg("url") if reqLog[value] != "" { - reqBuilder.WriteString(fmt.Sprintf("\tnavigate => %v\n", reqLog[value])) + _, _ = fmt.Fprintf(reqBuilder, "\tnavigate => %v\n", reqLog[value]) } else { - reqBuilder.WriteString(fmt.Sprintf("%v not found in %v\n", value, reqLog)) + fmt.Fprintf(reqBuilder, "%v not found in %v\n", value, reqLog) } } else { actStepStr := act.String() @@ -241,7 +243,7 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, payloads return true } newInput := input.Clone() - newInput.MetaInput.Input = gr.Request.URL.String() + newInput.MetaInput.Input = gr.Request.String() if err := request.executeRequestWithPayloads(newInput, gr.DynamicValues, previous, callback); err != nil { return false } diff --git a/pkg/protocols/http/build_request.go b/pkg/protocols/http/build_request.go index 1cb9553c9..291168265 100644 --- a/pkg/protocols/http/build_request.go +++ b/pkg/protocols/http/build_request.go @@ -115,7 +115,7 @@ func (g *generatedRequest) ApplyAuth(provider authprovider.AuthProvider) { func (g *generatedRequest) URL() string { if g.request != nil { - return g.request.URL.String() + return g.request.String() } if g.rawRequest != nil { return g.rawRequest.FullURL @@ -456,9 +456,9 @@ func (r *requestGenerator) fillRequest(req *retryablehttp.Request, values map[st if !LeaveDefaultPorts { switch { - case req.URL.Scheme == "http" && strings.HasSuffix(req.Host, ":80"): + case req.Scheme == "http" && strings.HasSuffix(req.Host, ":80"): req.Host = strings.TrimSuffix(req.Host, ":80") - case req.URL.Scheme == "https" && strings.HasSuffix(req.Host, ":443"): + case req.Scheme == "https" && strings.HasSuffix(req.Host, ":443"): req.Host = strings.TrimSuffix(req.Host, ":443") } } diff --git a/pkg/protocols/http/build_request_test.go b/pkg/protocols/http/build_request_test.go index 4405bd10b..2c3157923 100644 --- a/pkg/protocols/http/build_request_test.go +++ b/pkg/protocols/http/build_request_test.go @@ -46,7 +46,7 @@ func TestMakeRequestFromModal(t *testing.T) { t.Fatalf("url is nil in generator make") } bodyBytes, _ := req.request.BodyBytes() - require.Equal(t, "/login.php", req.request.URL.Path, "could not get correct request path") + require.Equal(t, "/login.php", req.request.Path, "could not get correct request path") require.Equal(t, "username=test&password=pass", string(bodyBytes), "could not get correct request body") } @@ -72,13 +72,13 @@ func TestMakeRequestFromModalTrimSuffixSlash(t *testing.T) { inputData, payloads, _ := generator.nextValue() req, err := generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com/test.php"), inputData, payloads, map[string]interface{}{}) require.Nil(t, err, "could not make http request") - require.Equal(t, "https://example.com/test.php?query=example", req.request.URL.String(), "could not get correct request path") + require.Equal(t, "https://example.com/test.php?query=example", req.request.String(), "could not get correct request path") generator = request.newGenerator(false) inputData, payloads, _ = generator.nextValue() req, err = generator.Make(context.Background(), contextargs.NewWithInput(context.Background(), "https://example.com/test/"), inputData, payloads, map[string]interface{}{}) require.Nil(t, err, "could not make http request") - require.Equal(t, "https://example.com/test/?query=example", req.request.URL.String(), "could not get correct request path") + require.Equal(t, "https://example.com/test/?query=example", req.request.String(), "could not get correct request path") } func TestMakeRequestFromRawWithPayloads(t *testing.T) { @@ -199,7 +199,7 @@ func TestMakeRequestFromModelUniqueInteractsh(t *testing.T) { require.Nil(t, err, "could not make http request") // check if all the interactsh markers are replaced with unique urls - require.NotContains(t, got.request.URL.String(), "{{interactsh-url}}", "could not get correct interactsh url") + require.NotContains(t, got.request.String(), "{{interactsh-url}}", "could not get correct interactsh url") // check the length of returned urls require.Equal(t, len(got.interactshURLs), 4, "could not get correct interactsh url") // check if the interactsh urls are unique diff --git a/pkg/protocols/http/cluster.go b/pkg/protocols/http/cluster.go index aa95c32ba..d0824ff03 100644 --- a/pkg/protocols/http/cluster.go +++ b/pkg/protocols/http/cluster.go @@ -17,5 +17,5 @@ func (request *Request) TmplClusterKey() uint64 { // IsClusterable returns true if the request is eligible to be clustered. func (request *Request) IsClusterable() bool { - return !(len(request.Payloads) > 0 || len(request.Fuzzing) > 0 || len(request.Raw) > 0 || len(request.Body) > 0 || request.Unsafe || request.NeedsRequestCondition() || request.Name != "") + return len(request.Payloads) <= 0 && len(request.Fuzzing) <= 0 && len(request.Raw) <= 0 && len(request.Body) <= 0 && !request.Unsafe && !request.NeedsRequestCondition() && request.Name == "" } diff --git a/pkg/protocols/http/race/syncedreadcloser.go b/pkg/protocols/http/race/syncedreadcloser.go index 4e48662c6..554bedc48 100644 --- a/pkg/protocols/http/race/syncedreadcloser.go +++ b/pkg/protocols/http/race/syncedreadcloser.go @@ -26,7 +26,7 @@ func NewSyncedReadCloser(r io.ReadCloser) *SyncedReadCloser { if err != nil { return nil } - r.Close() + _ = r.Close() s.length = int64(len(s.data)) s.openGate = make(chan struct{}) s.enableBlocking = true diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index f401fe4cf..a610534d7 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -743,7 +743,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ } else { //** For Normal requests **// hostname = generatedRequest.request.URL.Host - formedURL = generatedRequest.request.URL.String() + formedURL = generatedRequest.request.String() // if nuclei-project is available check if the request was already sent previously if request.options.ProjectFile != nil { // if unavailable fail silently @@ -822,7 +822,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ // rawhttp doesn't support draining response bodies. if resp != nil && resp.Body != nil && generatedRequest.rawRequest == nil && !generatedRequest.original.Pipeline { _, _ = io.CopyN(io.Discard, resp.Body, drainReqSize) - resp.Body.Close() + _ = resp.Body.Close() } request.options.Output.Request(request.options.TemplatePath, formedURL, request.Type().String(), err) request.options.Progress.IncrementErrorsBy(1) @@ -917,7 +917,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ } } if generatedRequest.request != nil { - matchedURL = generatedRequest.request.URL.String() + matchedURL = generatedRequest.request.String() } // Give precedence to the final URL from response if respChain.Request() != nil { diff --git a/pkg/protocols/http/request_annotations.go b/pkg/protocols/http/request_annotations.go index fa2a5eaed..1d01f8c96 100644 --- a/pkg/protocols/http/request_annotations.go +++ b/pkg/protocols/http/request_annotations.go @@ -76,9 +76,9 @@ func (r *Request) parseAnnotations(rawRequest string, request *retryablehttp.Req // handle scheme switch { case stringsutil.HasPrefixI(value, "http://"): - request.URL.Scheme = "http" + request.Scheme = "http" case stringsutil.HasPrefixI(value, "https://"): - request.URL.Scheme = "https" + request.Scheme = "https" } value = stringsutil.TrimPrefixAny(value, "http://", "https://") @@ -87,7 +87,7 @@ func (r *Request) parseAnnotations(rawRequest string, request *retryablehttp.Req request.URL.Host = value } else { hostPort := value - port := request.URL.Port() + port := request.Port() if port != "" { hostPort = net.JoinHostPort(hostPort, port) } diff --git a/pkg/protocols/http/request_annotations_test.go b/pkg/protocols/http/request_annotations_test.go index 3ca54d05c..bbc376f8a 100644 --- a/pkg/protocols/http/request_annotations_test.go +++ b/pkg/protocols/http/request_annotations_test.go @@ -23,7 +23,7 @@ func TestRequestParseAnnotationsSNI(t *testing.T) { overrides, modified := req.parseAnnotations(rawRequest, httpReq) require.True(t, modified, "could not apply request annotations") require.Equal(t, "github.com", overrides.request.TLS.ServerName) - require.Equal(t, "example.com", overrides.request.URL.Hostname()) + require.Equal(t, "example.com", overrides.request.Hostname()) }) t.Run("non-compliant-SNI-value", func(t *testing.T) { req := &Request{connConfiguration: &httpclientpool.Configuration{}} @@ -37,7 +37,7 @@ func TestRequestParseAnnotationsSNI(t *testing.T) { overrides, modified := req.parseAnnotations(rawRequest, httpReq) require.True(t, modified, "could not apply request annotations") require.Equal(t, "${jndi:ldap://${hostName}.test.com}", overrides.request.TLS.ServerName) - require.Equal(t, "example.com", overrides.request.URL.Hostname()) + require.Equal(t, "example.com", overrides.request.Hostname()) }) } diff --git a/pkg/protocols/http/request_fuzz.go b/pkg/protocols/http/request_fuzz.go index b207436ad..c800b6aff 100644 --- a/pkg/protocols/http/request_fuzz.go +++ b/pkg/protocols/http/request_fuzz.go @@ -63,7 +63,7 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, previous return errors.Wrap(err, "fuzz: could not build request obtained from target file") } request.addHeadersToRequest(baseRequest) - input.MetaInput.Input = baseRequest.URL.String() + input.MetaInput.Input = baseRequest.String() // execute with one value first to checks its applicability err = request.executeAllFuzzingRules(input, previous, baseRequest, callback) if err != nil { @@ -220,9 +220,9 @@ func (request *Request) executeGeneratedFuzzingRequest(gr fuzz.GeneratedRequest, } if request.options.FuzzParamsFrequency != nil && !setInteractshCallback { if !gotMatches { - request.options.FuzzParamsFrequency.MarkParameter(gr.Parameter, gr.Request.URL.String(), request.options.TemplateID) + request.options.FuzzParamsFrequency.MarkParameter(gr.Parameter, gr.Request.String(), request.options.TemplateID) } else { - request.options.FuzzParamsFrequency.UnmarkParameter(gr.Parameter, gr.Request.URL.String(), request.options.TemplateID) + request.options.FuzzParamsFrequency.UnmarkParameter(gr.Parameter, gr.Request.String(), request.options.TemplateID) } } }, 0) @@ -311,7 +311,7 @@ func (request *Request) filterDataMap(input *contextargs.Context) map[string]int if strings.EqualFold(k, "content_type") { m["content_type"] = v } - sb.WriteString(fmt.Sprintf("%s: %s\n", k, v)) + fmt.Fprintf(sb, "%s: %s\n", k, v) return true }) m["header"] = sb.String() diff --git a/pkg/protocols/http/request_test.go b/pkg/protocols/http/request_test.go index c0bd2bb34..0cdabba91 100644 --- a/pkg/protocols/http/request_test.go +++ b/pkg/protocols/http/request_test.go @@ -66,7 +66,7 @@ Disallow: /a Disallow: /b Disallow: /c`)) default: - _, _ = w.Write([]byte(fmt.Sprintf(`match %v`, r.URL.Path))) + _, _ = fmt.Fprintf(w, `match %v`, r.URL.Path) } })) defer ts.Close() diff --git a/pkg/protocols/http/signerpool/signerpool.go b/pkg/protocols/http/signerpool/signerpool.go index 65ee50697..f4fecf763 100644 --- a/pkg/protocols/http/signerpool/signerpool.go +++ b/pkg/protocols/http/signerpool/signerpool.go @@ -30,7 +30,7 @@ type Configuration struct { // Hash returns the hash of the configuration to allow client pooling func (c *Configuration) Hash() string { builder := &strings.Builder{} - builder.WriteString(fmt.Sprintf("%v", c.SignerArgs)) + _, _ = fmt.Fprintf(builder, "%v", c.SignerArgs) hash := builder.String() return hash } diff --git a/pkg/protocols/http/utils.go b/pkg/protocols/http/utils.go index 875faaf21..92aa870dc 100644 --- a/pkg/protocols/http/utils.go +++ b/pkg/protocols/http/utils.go @@ -14,7 +14,7 @@ func dump(req *generatedRequest, reqURL string) ([]byte, error) { if req.request != nil { bin, err := req.request.Dump() if err != nil { - return nil, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", req.request.URL.String()) + return nil, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", req.request.String()) } return bin, nil } diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index 197ef5332..77b49c6bd 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -302,7 +302,9 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac request.options.Progress.IncrementFailedRequestsBy(1) return errors.Wrap(err, "could not connect to server") } - defer conn.Close() + defer func() { + _ = conn.Close() + }() _ = conn.SetDeadline(time.Now().Add(time.Duration(request.options.Options.Timeout) * time.Second)) var interactshURLs []string @@ -508,10 +510,11 @@ func getAddress(toTest string) (string, error) { } func ConnReadNWithTimeout(conn net.Conn, n int64, timeout time.Duration) ([]byte, error) { - if n == -1 { + switch n { + case -1: // if n is -1 then read all available data from connection return reader.ConnReadNWithTimeout(conn, -1, timeout) - } else if n == 0 { + case 0: n = 4096 // default buffer size } b := make([]byte, n) diff --git a/pkg/protocols/offlinehttp/find_test.go b/pkg/protocols/offlinehttp/find_test.go index 83249bc97..acbfdf49b 100644 --- a/pkg/protocols/offlinehttp/find_test.go +++ b/pkg/protocols/offlinehttp/find_test.go @@ -30,7 +30,9 @@ func TestFindResponses(t *testing.T) { tempDir, err := os.MkdirTemp("", "test-*") require.Nil(t, err, "could not create temporary directory") - defer os.RemoveAll(tempDir) + defer func() { + _ = os.RemoveAll(tempDir) + }() files := map[string]string{ "test.go": "TEST", diff --git a/pkg/protocols/offlinehttp/read_response_test.go b/pkg/protocols/offlinehttp/read_response_test.go index da1382bac..a82f58843 100644 --- a/pkg/protocols/offlinehttp/read_response_test.go +++ b/pkg/protocols/offlinehttp/read_response_test.go @@ -161,7 +161,7 @@ Server: Google Frontend router := httprouter.New() router.GET("/", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { w.Header().Add("Server", "Google Frontend") - fmt.Fprintf(w, "%s", ` + _, _ = fmt.Fprintf(w, "%s", ` Firing Range @@ -182,7 +182,9 @@ Server: Google Frontend data, err := client.Get(ts.URL) require.Nil(t, err, "could not dial url") - defer data.Body.Close() + defer func() { + _ = data.Body.Close() + }() b, err := httputil.DumpResponse(data, true) require.Nil(t, err, "could not dump response") diff --git a/pkg/protocols/offlinehttp/request.go b/pkg/protocols/offlinehttp/request.go index 07a0fc2dc..8849b44ab 100644 --- a/pkg/protocols/offlinehttp/request.go +++ b/pkg/protocols/offlinehttp/request.go @@ -57,7 +57,9 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, gologger.Error().Msgf("Could not open file path %s: %s\n", data, err) return } - defer file.Close() + defer func() { + _ = file.Close() + }() stat, err := file.Stat() if err != nil { diff --git a/pkg/protocols/ssl/ssl.go b/pkg/protocols/ssl/ssl.go index 8943d597d..cc73930e9 100644 --- a/pkg/protocols/ssl/ssl.go +++ b/pkg/protocols/ssl/ssl.go @@ -108,7 +108,7 @@ func (request *Request) TmplClusterKey() uint64 { } func (request *Request) IsClusterable() bool { - return !(len(request.CipherSuites) > 0 || request.MinVersion != "" || request.MaxVersion != "") + return len(request.CipherSuites) <= 0 && request.MinVersion == "" && request.MaxVersion == "" } // Compile compiles the request generators preparing any requests possible. diff --git a/pkg/protocols/utils/variables.go b/pkg/protocols/utils/variables.go index 5e5287420..00f22a118 100644 --- a/pkg/protocols/utils/variables.go +++ b/pkg/protocols/utils/variables.go @@ -120,9 +120,10 @@ func generateVariables(inputURL *urlutil.URL, removeTrailingSlash bool) map[stri parsed.Params = urlutil.NewOrderedParams() port := parsed.Port() if port == "" { - if parsed.Scheme == "https" { + switch parsed.Scheme { + case "https": port = "443" - } else if parsed.Scheme == "http" { + case "http": port = "80" } } diff --git a/pkg/protocols/websocket/websocket.go b/pkg/protocols/websocket/websocket.go index 02cf75190..e17e5512a 100644 --- a/pkg/protocols/websocket/websocket.go +++ b/pkg/protocols/websocket/websocket.go @@ -235,7 +235,9 @@ func (request *Request) executeRequestWithPayloads(target *contextargs.Context, requestOptions.Progress.IncrementFailedRequestsBy(1) return errors.Wrap(err, "could not connect to server") } - defer conn.Close() + defer func() { + _ = conn.Close() + }() responseBuilder := &strings.Builder{} if readBuffer != nil { diff --git a/pkg/reporting/dedupe/dedupe.go b/pkg/reporting/dedupe/dedupe.go index 1ac7a0b2d..ae7b47c48 100644 --- a/pkg/reporting/dedupe/dedupe.go +++ b/pkg/reporting/dedupe/dedupe.go @@ -64,9 +64,9 @@ func (s *Storage) Clear() { // Close closes the storage for further operations func (s *Storage) Close() { - s.storage.Close() + _ = s.storage.Close() if s.temporary != "" { - os.RemoveAll(s.temporary) + _ = os.RemoveAll(s.temporary) } } diff --git a/pkg/reporting/dedupe/dedupe_test.go b/pkg/reporting/dedupe/dedupe_test.go index 0a6d84b0f..74621a798 100644 --- a/pkg/reporting/dedupe/dedupe_test.go +++ b/pkg/reporting/dedupe/dedupe_test.go @@ -12,7 +12,9 @@ import ( func TestDedupeDuplicates(t *testing.T) { tempDir, err := os.MkdirTemp("", "nuclei") require.Nil(t, err, "could not create temporary storage") - defer os.RemoveAll(tempDir) + defer func() { + _ = os.RemoveAll(tempDir) + }() storage, err := New(tempDir) require.Nil(t, err, "could not create duplicate storage") diff --git a/pkg/reporting/exporters/es/elasticsearch.go b/pkg/reporting/exporters/es/elasticsearch.go index b17b97a87..4a1cc7e7c 100644 --- a/pkg/reporting/exporters/es/elasticsearch.go +++ b/pkg/reporting/exporters/es/elasticsearch.go @@ -131,7 +131,9 @@ func (exporter *Exporter) Export(event *output.ResultEvent) error { if err != nil { return err } - defer res.Body.Close() + defer func() { + _ = res.Body.Close() + }() b, err = io.ReadAll(res.Body) if err != nil { diff --git a/pkg/reporting/exporters/markdown/markdown.go b/pkg/reporting/exporters/markdown/markdown.go index b294c971e..fb1d4df0f 100644 --- a/pkg/reporting/exporters/markdown/markdown.go +++ b/pkg/reporting/exporters/markdown/markdown.go @@ -62,7 +62,9 @@ func (exporter *Exporter) Export(event *output.ResultEvent) error { if err != nil { return err } - defer file.Close() + defer func() { + _ = file.Close() + }() filename := createFileName(event) diff --git a/pkg/reporting/format/format_utils.go b/pkg/reporting/format/format_utils.go index 92976d30f..a85359e8b 100644 --- a/pkg/reporting/format/format_utils.go +++ b/pkg/reporting/format/format_utils.go @@ -45,14 +45,14 @@ var ( func CreateReportDescription(event *output.ResultEvent, formatter ResultFormatter, omitRaw bool) string { template := GetMatchedTemplateName(event) builder := &bytes.Buffer{} - builder.WriteString(fmt.Sprintf("%s: %s matched at %s\n\n", formatter.MakeBold("Details"), formatter.MakeBold(template), event.Host)) + fmt.Fprintf(builder, "%s: %s matched at %s\n\n", formatter.MakeBold("Details"), formatter.MakeBold(template), event.Host) attributes := utils.NewEmptyInsertionOrderedStringMap(3) attributes.Set("Protocol", strings.ToUpper(event.Type)) attributes.Set("Full URL", event.Matched) attributes.Set("Timestamp", event.Timestamp.Format("Mon Jan 2 15:04:05 -0700 MST 2006")) attributes.ForEach(func(key string, data interface{}) { - builder.WriteString(fmt.Sprintf("%s: %s\n\n", formatter.MakeBold(key), types.ToString(data))) + fmt.Fprintf(builder, "%s: %s\n\n", formatter.MakeBold(key), types.ToString(data)) }) if len(ReportGenerationMetadataHooks) > 0 { @@ -120,12 +120,12 @@ func CreateReportDescription(event *output.ResultEvent, formatter ResultFormatte } } if event.Interaction != nil { - builder.WriteString(fmt.Sprintf("%s\n%s", formatter.MakeBold("Interaction Data"), formatter.CreateHorizontalLine())) + fmt.Fprintf(builder, "%s\n%s", formatter.MakeBold("Interaction Data"), formatter.CreateHorizontalLine()) builder.WriteString(event.Interaction.Protocol) if event.Interaction.QType != "" { - builder.WriteString(fmt.Sprintf(" (%s)", event.Interaction.QType)) + _, _ = fmt.Fprintf(builder, " (%s)", event.Interaction.QType) } - builder.WriteString(fmt.Sprintf(" Interaction from %s at %s", event.Interaction.RemoteAddress, event.Interaction.UniqueID)) + fmt.Fprintf(builder, " Interaction from %s at %s", event.Interaction.RemoteAddress, event.Interaction.UniqueID) if event.Interaction.RawRequest != "" { builder.WriteString(formatter.CreateCodeBlock("Interaction Request", event.Interaction.RawRequest, "")) @@ -157,7 +157,7 @@ func CreateReportDescription(event *output.ResultEvent, formatter ResultFormatte } builder.WriteString("\n" + formatter.CreateHorizontalLine() + "\n") - builder.WriteString(fmt.Sprintf("Generated by %s", formatter.CreateLink("Nuclei "+config.Version, "https://github.com/projectdiscovery/nuclei"))) + _, _ = fmt.Fprintf(builder, "Generated by %s", formatter.CreateLink("Nuclei "+config.Version, "https://github.com/projectdiscovery/nuclei")) data := builder.String() return data } diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index 97b8d6924..a759ab282 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -227,7 +227,9 @@ func CreateConfigIfNotExists() error { if err != nil { return errorutil.NewWithErr(err).Msgf("could not create config file") } - defer reportingFile.Close() + defer func() { + _ = reportingFile.Close() + }() err = yaml.NewEncoder(reportingFile).Encode(options) return err @@ -270,7 +272,7 @@ func (c *ReportingClient) Close() { c.dedupe.Close() } for _, exporter := range c.exporters { - exporter.Close() + _ = exporter.Close() } } diff --git a/pkg/reporting/trackers/gitlab/gitlab.go b/pkg/reporting/trackers/gitlab/gitlab.go index 75782502b..3a0ab8397 100644 --- a/pkg/reporting/trackers/gitlab/gitlab.go +++ b/pkg/reporting/trackers/gitlab/gitlab.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/xanzy/go-gitlab" + gitlab "gitlab.com/gitlab-org/api/client-go" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/markdown/util" diff --git a/pkg/reporting/trackers/linear/linear.go b/pkg/reporting/trackers/linear/linear.go index 7a934a727..24b464f33 100644 --- a/pkg/reporting/trackers/linear/linear.go +++ b/pkg/reporting/trackers/linear/linear.go @@ -384,7 +384,9 @@ func (i *Integration) doGraphqlRequest(ctx context.Context, query string, v any, if err != nil { return err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("non-200 OK status code: %v body: %q", resp.Status, body) diff --git a/pkg/scan/charts/charts.go b/pkg/scan/charts/charts.go index 44f842fd8..e651b7152 100644 --- a/pkg/scan/charts/charts.go +++ b/pkg/scan/charts/charts.go @@ -54,7 +54,9 @@ func NewScanEventsCharts(eventsDir string) (*ScanEventsCharts, error) { if err != nil { return nil, err } - defer f.Close() + defer func() { + _ = f.Close() + }() data := []events.ScanEvent{} dec := json.NewDecoder(f) diff --git a/pkg/scan/charts/echarts.go b/pkg/scan/charts/echarts.go index 69960588d..719292196 100644 --- a/pkg/scan/charts/echarts.go +++ b/pkg/scan/charts/echarts.go @@ -30,7 +30,9 @@ func (s *ScanEventsCharts) GenerateHTML(filePath string) error { if err != nil { return err } - defer output.Close() + defer func() { + _ = output.Close() + }() return page.Render(output) } @@ -48,7 +50,7 @@ func (s *ScanEventsCharts) allCharts(c echo.Context) *components.Page { // line3.SetSpacerHeight(SpacerHeight) page.AddCharts(line1, kline, line2, line3) page.SetLayout(components.PageCenterLayout) - page.Theme = "dark" + // page.Theme = "dark" page.Validate() return page @@ -69,7 +71,7 @@ func (s *ScanEventsCharts) totalRequestsOverTime(c echo.Context) *charts.Line { }), ) - var startTime time.Time = time.Now() + var startTime = time.Now() var endTime time.Time for _, event := range s.data { @@ -99,20 +101,20 @@ func (s *ScanEventsCharts) totalRequestsOverTime(c echo.Context) *charts.Line { Name: scanEvent.TemplateID, }) } - line.AddSeries(k, lineData, charts.WithLineChartOpts(opts.LineChart{Smooth: false}), charts.WithLabelOpts(opts.Label{Show: true, Position: "top"})) + line.AddSeries(k, lineData, charts.WithLineChartOpts(opts.LineChart{Smooth: opts.Bool(false)}), charts.WithLabelOpts(opts.Label{Show: opts.Bool(true), Position: "top"})) } line.SetGlobalOptions( charts.WithTitleOpts(opts.Title{Title: "Nuclei: total-req vs time"}), - charts.WithXAxisOpts(opts.XAxis{Name: "Time", Type: "time", AxisLabel: &opts.AxisLabel{Show: true, ShowMaxLabel: true, Formatter: opts.FuncOpts(`function (date) { return (date/1000)+'s'; }`)}}), + charts.WithXAxisOpts(opts.XAxis{Name: "Time", Type: "time", AxisLabel: &opts.AxisLabel{Show: opts.Bool(true), ShowMaxLabel: opts.Bool(true), Formatter: opts.FuncOpts(`function (date) { return (date/1000)+'s'; }`)}}), charts.WithYAxisOpts(opts.YAxis{Name: "Requests Sent", Type: "value"}), charts.WithInitializationOpts(opts.Initialization{Theme: "dark"}), charts.WithDataZoomOpts(opts.DataZoom{Type: "slider", Start: 0, End: 100}), charts.WithGridOpts(opts.Grid{Left: "10%", Right: "10%", Bottom: "15%", Top: "20%"}), - charts.WithToolboxOpts(opts.Toolbox{Show: true, Feature: &opts.ToolBoxFeature{ - SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: true, Name: "save", Title: "save"}, - DataZoom: &opts.ToolBoxFeatureDataZoom{Show: true, Title: map[string]string{"zoom": "zoom", "back": "back"}}, - DataView: &opts.ToolBoxFeatureDataView{Show: true, Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, + charts.WithToolboxOpts(opts.Toolbox{Show: opts.Bool(true), Feature: &opts.ToolBoxFeature{ + SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: opts.Bool(true), Name: "save", Title: "save"}, + DataZoom: &opts.ToolBoxFeatureDataZoom{Show: opts.Bool(true), Title: map[string]string{"zoom": "zoom", "back": "back"}}, + DataView: &opts.ToolBoxFeatureDataView{Show: opts.Bool(true), Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, }}), ) @@ -135,7 +137,7 @@ func (s *ScanEventsCharts) topSlowTemplates(c echo.Context) *charts.Kline { }), ) ids := map[string][]int64{} - var startTime time.Time = time.Now() + var startTime = time.Now() for _, event := range s.data { if event.Time.Before(startTime) { startTime = event.Time @@ -182,22 +184,22 @@ func (s *ScanEventsCharts) topSlowTemplates(c echo.Context) *charts.Kline { charts.WithTitleOpts(opts.Title{Title: fmt.Sprintf("Nuclei: Top %v Slow Templates", TopK)}), charts.WithXAxisOpts(opts.XAxis{ Type: "category", - Show: true, - AxisLabel: &opts.AxisLabel{Rotate: 90, Show: true, ShowMinLabel: true, ShowMaxLabel: true, Formatter: opts.FuncOpts(`function (value) { return value; }`)}, + Show: opts.Bool(true), + AxisLabel: &opts.AxisLabel{Rotate: 90, Show: opts.Bool(true), ShowMinLabel: opts.Bool(true), ShowMaxLabel: opts.Bool(true), Formatter: opts.FuncOpts(`function (value) { return value; }`)}, }), charts.WithYAxisOpts(opts.YAxis{ - Scale: true, + Scale: opts.Bool(true), Type: "value", - Show: true, - AxisLabel: &opts.AxisLabel{Show: true, Formatter: opts.FuncOpts(`function (ms) { return Math.floor(ms/60000) + 'm' + Math.floor((ms/60000 - Math.floor(ms/60000))*60) + 's'; }`)}, + Show: opts.Bool(true), + AxisLabel: &opts.AxisLabel{Show: opts.Bool(true), Formatter: opts.FuncOpts(`function (ms) { return Math.floor(ms/60000) + 'm' + Math.floor((ms/60000 - Math.floor(ms/60000))*60) + 's'; }`)}, }), charts.WithDataZoomOpts(opts.DataZoom{Type: "slider", Start: 0, End: 100}), charts.WithGridOpts(opts.Grid{Left: "10%", Right: "10%", Bottom: "40%", Top: "10%"}), - charts.WithTooltipOpts(opts.Tooltip{Show: true, Trigger: "events.ScanEvent", TriggerOn: "mousemove|click", Enterable: true, Formatter: opts.FuncOpts(`function (params) { return params.name ; }`)}), - charts.WithToolboxOpts(opts.Toolbox{Show: true, Feature: &opts.ToolBoxFeature{ - SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: true, Name: "save", Title: "save"}, - DataZoom: &opts.ToolBoxFeatureDataZoom{Show: true, Title: map[string]string{"zoom": "zoom", "back": "back"}}, - DataView: &opts.ToolBoxFeatureDataView{Show: true, Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, + charts.WithTooltipOpts(opts.Tooltip{Show: opts.Bool(true), Trigger: "item", TriggerOn: "mousemove|click", Enterable: opts.Bool(true), Formatter: opts.FuncOpts(`function (params) { return params.name ; }`)}), + charts.WithToolboxOpts(opts.Toolbox{Show: opts.Bool(true), Feature: &opts.ToolBoxFeature{ + SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: opts.Bool(true), Name: "save", Title: "save"}, + DataZoom: &opts.ToolBoxFeatureDataZoom{Show: opts.Bool(true), Title: map[string]string{"zoom": "zoom", "back": "back"}}, + DataView: &opts.ToolBoxFeatureDataView{Show: opts.Bool(true), Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, }}), ) @@ -255,20 +257,20 @@ func (s *ScanEventsCharts) requestsVSInterval(c echo.Context) *charts.Line { data = append(data, opts.LineData{Value: temp, Name: s.data[len(s.data)-1].Time.Sub(orig).String()}) } line.SetXAxis(xaxisData) - line.AddSeries("RPS", data, charts.WithLineChartOpts(opts.LineChart{Smooth: false}), charts.WithLabelOpts(opts.Label{Show: true, Position: "top"})) + line.AddSeries("RPS", data, charts.WithLineChartOpts(opts.LineChart{Smooth: opts.Bool(false)}), charts.WithLabelOpts(opts.Label{Show: opts.Bool(true), Position: "top"})) } line.SetGlobalOptions( charts.WithTitleOpts(opts.Title{Title: "Nuclei: Template Execution", Subtitle: "Time Interval: " + interval.String()}), - charts.WithXAxisOpts(opts.XAxis{Name: "Time Intervals", Type: "category", AxisLabel: &opts.AxisLabel{Show: true, ShowMaxLabel: true, Formatter: opts.FuncOpts(`function (date) { return (date/1000)+'s'; }`)}}), - charts.WithYAxisOpts(opts.YAxis{Name: "RPS Value", Type: "value", Show: true}), + charts.WithXAxisOpts(opts.XAxis{Name: "Time Intervals", Type: "category", AxisLabel: &opts.AxisLabel{Show: opts.Bool(true), ShowMaxLabel: opts.Bool(true), Formatter: opts.FuncOpts(`function (date) { return (date/1000)+'s'; }`)}}), + charts.WithYAxisOpts(opts.YAxis{Name: "RPS Value", Type: "value", Show: opts.Bool(true)}), charts.WithInitializationOpts(opts.Initialization{Theme: "dark"}), charts.WithDataZoomOpts(opts.DataZoom{Type: "slider", Start: 0, End: 100}), charts.WithGridOpts(opts.Grid{Left: "10%", Right: "10%", Bottom: "15%", Top: "20%"}), - charts.WithToolboxOpts(opts.Toolbox{Show: true, Feature: &opts.ToolBoxFeature{ - SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: true, Name: "save", Title: "save"}, - DataZoom: &opts.ToolBoxFeatureDataZoom{Show: true, Title: map[string]string{"zoom": "zoom", "back": "back"}}, - DataView: &opts.ToolBoxFeatureDataView{Show: true, Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, + charts.WithToolboxOpts(opts.Toolbox{Show: opts.Bool(true), Feature: &opts.ToolBoxFeature{ + SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: opts.Bool(true), Name: "save", Title: "save"}, + DataZoom: &opts.ToolBoxFeatureDataZoom{Show: opts.Bool(true), Title: map[string]string{"zoom": "zoom", "back": "back"}}, + DataView: &opts.ToolBoxFeatureDataView{Show: opts.Bool(true), Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, }}), ) @@ -343,19 +345,19 @@ func (s *ScanEventsCharts) concurrencyVsTime(c echo.Context) *charts.Line { xaxisData = append(xaxisData, tempTime.Milliseconds()) } line.SetXAxis(xaxisData) - line.AddSeries("Concurrency", plotData, charts.WithLineChartOpts(opts.LineChart{Smooth: false}), charts.WithLabelOpts(opts.Label{Show: true, Position: "top"})) + line.AddSeries("Concurrency", plotData, charts.WithLineChartOpts(opts.LineChart{Smooth: opts.Bool(false)}), charts.WithLabelOpts(opts.Label{Show: opts.Bool(true), Position: "top"})) line.SetGlobalOptions( charts.WithTitleOpts(opts.Title{Title: "Nuclei: WorkerPool", Subtitle: "Time Interval: " + interval.String()}), - charts.WithXAxisOpts(opts.XAxis{Name: "Time Intervals", Type: "category", AxisLabel: &opts.AxisLabel{Show: true, ShowMaxLabel: true, Formatter: opts.FuncOpts(`function (date) { return (date/1000)+'s'; }`)}}), - charts.WithYAxisOpts(opts.YAxis{Name: "Total Workers", Type: "value", Show: true}), + charts.WithXAxisOpts(opts.XAxis{Name: "Time Intervals", Type: "category", AxisLabel: &opts.AxisLabel{Show: opts.Bool(true), ShowMaxLabel: opts.Bool(true), Formatter: opts.FuncOpts(`function (date) { return (date/1000)+'s'; }`)}}), + charts.WithYAxisOpts(opts.YAxis{Name: "Total Workers", Type: "value", Show: opts.Bool(true)}), charts.WithInitializationOpts(opts.Initialization{Theme: "dark"}), charts.WithDataZoomOpts(opts.DataZoom{Type: "slider", Start: 0, End: 100}), charts.WithGridOpts(opts.Grid{Left: "10%", Right: "10%", Bottom: "15%", Top: "20%"}), - charts.WithToolboxOpts(opts.Toolbox{Show: true, Feature: &opts.ToolBoxFeature{ - SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: true, Name: "save", Title: "save"}, - DataZoom: &opts.ToolBoxFeatureDataZoom{Show: true, Title: map[string]string{"zoom": "zoom", "back": "back"}}, - DataView: &opts.ToolBoxFeatureDataView{Show: true, Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, + charts.WithToolboxOpts(opts.Toolbox{Show: opts.Bool(true), Feature: &opts.ToolBoxFeature{ + SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{Show: opts.Bool(true), Name: "save", Title: "save"}, + DataZoom: &opts.ToolBoxFeatureDataZoom{Show: opts.Bool(true), Title: map[string]string{"zoom": "zoom", "back": "back"}}, + DataView: &opts.ToolBoxFeatureDataView{Show: opts.Bool(true), Title: "raw", Lang: []string{"raw", "exit", "refresh"}}, }}), ) diff --git a/pkg/templates/cluster.go b/pkg/templates/cluster.go index 03ad79c60..8008eb0e5 100644 --- a/pkg/templates/cluster.go +++ b/pkg/templates/cluster.go @@ -201,15 +201,16 @@ func NewClusterExecuter(requests []*Template, options *protocols.ExecutorOptions }) } for _, req := range requests { - if executer.templateType == types.DNSProtocol { + switch executer.templateType { + case types.DNSProtocol: if req.RequestsDNS[0].CompiledOperators != nil { appendOperator(req, req.RequestsDNS[0].CompiledOperators) } - } else if executer.templateType == types.HTTPProtocol { + case types.HTTPProtocol: if req.RequestsHTTP[0].CompiledOperators != nil { appendOperator(req, req.RequestsHTTP[0].CompiledOperators) } - } else if executer.templateType == types.SSLProtocol { + case types.SSLProtocol: if req.RequestsSSL[0].CompiledOperators != nil { appendOperator(req, req.RequestsSSL[0].CompiledOperators) } diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index d8b568957..ce51a5ccf 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -75,7 +75,9 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Executo } } - defer reader.Close() + defer func() { + _ = reader.Close() + }() options.TemplatePath = filePath template, err := ParseTemplateFromReader(reader, preprocessor, options.Copy()) @@ -460,7 +462,7 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e } } options.TemplateVerifier = template.TemplateVerifier - if !(template.Verified && verifier.Identifier() == "projectdiscovery/nuclei-templates") { + if !template.Verified || verifier.Identifier() != "projectdiscovery/nuclei-templates" { template.Options.RawTemplate = data } return template, nil diff --git a/pkg/templates/parser.go b/pkg/templates/parser.go index c946fbb7b..7f481dc85 100644 --- a/pkg/templates/parser.go +++ b/pkg/templates/parser.go @@ -96,7 +96,9 @@ func (p *Parser) ParseTemplate(templatePath string, catalog catalog.Catalog) (an if err != nil { return nil, err } - defer reader.Close() + defer func() { + _ = reader.Close() + }() data, err := io.ReadAll(reader) if err != nil { diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index 942988cf8..7726fc7c9 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -187,7 +187,7 @@ func (template *Template) Type() types.ProtocolType { return types.CodeProtocol case len(template.RequestsJavascript) > 0: return types.JavascriptProtocol - case len(template.Workflow.Workflows) > 0: + case len(template.Workflows) > 0: return types.WorkflowProtocol default: return types.InvalidProtocol @@ -389,7 +389,9 @@ func (template *Template) ImportFileRefs(options *protocols.ExecutorOptions) err // load file respecting sandbox data, err := options.Options.LoadHelperFile(source, options.TemplatePath, options.Catalog) if err == nil { - defer data.Close() + defer func() { + _ = data.Close() + }() bin, err := io.ReadAll(data) if err == nil { return string(bin), true diff --git a/pkg/testutils/fuzzplayground/db.go b/pkg/testutils/fuzzplayground/db.go index 8344f5dc4..47b506adb 100644 --- a/pkg/testutils/fuzzplayground/db.go +++ b/pkg/testutils/fuzzplayground/db.go @@ -134,7 +134,9 @@ func getUnsanitizedPostsByLang(db *sql.DB, lang string) ([]Posts, error) { if err != nil { return nil, err } - defer rows.Close() + defer func() { + _ = rows.Close() + }() for rows.Next() { var post Posts diff --git a/pkg/testutils/fuzzplayground/server.go b/pkg/testutils/fuzzplayground/server.go index af42552cb..519a17d51 100644 --- a/pkg/testutils/fuzzplayground/server.go +++ b/pkg/testutils/fuzzplayground/server.go @@ -80,7 +80,9 @@ func requestHandler(ctx echo.Context) error { if err != nil { return ctx.HTML(500, err.Error()) } - defer data.Body.Close() + defer func() { + _ = data.Body.Close() + }() body, _ := io.ReadAll(data.Body) return ctx.HTML(200, fmt.Sprintf(bodyTemplate, string(body))) @@ -172,7 +174,9 @@ func resetPasswordHandler(c echo.Context) error { if err != nil { return c.JSON(500, "Something went wrong") } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() return c.JSON(200, "Password reset successfully") } @@ -184,7 +188,9 @@ func hostHeaderLabHandler(c echo.Context) error { if err != nil { return c.JSON(500, "Something went wrong") } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() c.Response().Header().Set("Content-Type", resp.Header.Get("Content-Type")) c.Response().WriteHeader(resp.StatusCode) _, err = io.Copy(c.Response().Writer, resp.Body) diff --git a/pkg/testutils/integration.go b/pkg/testutils/integration.go index d423be462..3c5e33f6d 100644 --- a/pkg/testutils/integration.go +++ b/pkg/testutils/integration.go @@ -323,7 +323,7 @@ func NewTCPServer(tlsConfig *tls.Config, port int, handler func(conn net.Conn)) // Close closes the TCP server func (s *TCPServer) Close() { - s.listener.Close() + _ = s.listener.Close() } // NewWebsocketServer creates a new websocket server from a handler @@ -338,7 +338,9 @@ func NewWebsocketServer(path string, handler func(conn net.Conn), originValidate return } go func() { - defer conn.Close() + defer func() { + _ = conn.Close() + }() handler(conn) }() diff --git a/pkg/tmplexec/flow/flow_executor.go b/pkg/tmplexec/flow/flow_executor.go index a8c554679..2334eecee 100644 --- a/pkg/tmplexec/flow/flow_executor.go +++ b/pkg/tmplexec/flow/flow_executor.go @@ -294,7 +294,9 @@ func (f *FlowExecutor) ReadDataFromFile(payload string) ([]string, error) { if err != nil { return values, err } - defer reader.Close() + defer func() { + _ = reader.Close() + }() bin, err := io.ReadAll(reader) if err != nil { return values, err diff --git a/pkg/tmplexec/flow/flow_internal.go b/pkg/tmplexec/flow/flow_internal.go index 03cc29596..927b2d6c9 100644 --- a/pkg/tmplexec/flow/flow_internal.go +++ b/pkg/tmplexec/flow/flow_internal.go @@ -20,7 +20,7 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma f.options.GetTemplateCtx(f.ctx.Input.MetaInput).Merge(variableMap) // merge all variables into template context // to avoid polling update template variables everytime we execute a protocol - var m map[string]interface{} = f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll() + var m = f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll() _ = runtime.Set("template", m) }() matcherStatus := &atomic.Bool{} // due to interactsh matcher polling logic this needs to be atomic bool diff --git a/pkg/utils/json/doc.go b/pkg/utils/json/doc.go index b3eb7d24a..b9cc45cfd 100644 --- a/pkg/utils/json/doc.go +++ b/pkg/utils/json/doc.go @@ -1,7 +1,7 @@ // Package json provides fast JSON encoding and decoding functionality. // // On supported platforms; Linux, Darwin, or Windows on amd64, or on arm64 with -// Go >= 1.20 and <= 1.23, the package uses the high-performance [sonic] library. +// Go >= 1.20 and <= 1.24, the package uses the high-performance [sonic] library. // On any other systems, it gracefully falls back to using the [go-json] // implementation. // diff --git a/pkg/utils/json/json.go b/pkg/utils/json/json.go index c9d9e39ab..054640695 100644 --- a/pkg/utils/json/json.go +++ b/pkg/utils/json/json.go @@ -1,5 +1,4 @@ -//go:build !go1.24 && (linux || darwin || windows) && (amd64 || arm64) -// +build !go1.24 +//go:build (linux || darwin || windows) && (amd64 || arm64) // +build linux darwin windows // +build amd64 arm64 diff --git a/pkg/utils/json/json_fallback.go b/pkg/utils/json/json_fallback.go index 495cbaeda..3c87dd922 100644 --- a/pkg/utils/json/json_fallback.go +++ b/pkg/utils/json/json_fallback.go @@ -1,5 +1,5 @@ -//go:build go1.24 || !(linux || darwin || windows) || !(amd64 || arm64) -// +build go1.24 !linux,!darwin,!windows !amd64,!arm64 +//go:build !(linux || darwin || windows) || !(amd64 || arm64) +// +build !linux,!darwin,!windows !amd64,!arm64 package json From db916199c264d7aa8793b97683bbd5193cdd001a Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Tue, 1 Jul 2025 00:48:41 +0700 Subject: [PATCH 044/135] Bump version to v3.4.6 --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index f7036431a..bb78cbd07 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.5` + Version = `v3.4.6` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From 5f2082cf3490ed4fc4e159bedb3c5e85a2cf77e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 20:46:02 +0000 Subject: [PATCH 045/135] chore(deps): bump the go_modules group across 1 directory with 3 updates Bumps the go_modules group with 3 updates in the / directory: [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin), [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) and [github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt). Updates `github.com/gin-gonic/gin` from 1.9.0 to 1.9.1 - [Release notes](https://github.com/gin-gonic/gin/releases) - [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md) - [Commits](https://github.com/gin-gonic/gin/compare/v1.9.0...v1.9.1) Updates `github.com/go-viper/mapstructure/v2` from 2.2.1 to 2.3.0 - [Release notes](https://github.com/go-viper/mapstructure/releases) - [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md) - [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0) Updates `github.com/golang-jwt/jwt/v4` from 4.5.0 to 4.5.2 - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v4.5.0...v4.5.2) --- updated-dependencies: - dependency-name: github.com/gin-gonic/gin dependency-version: 1.9.1 dependency-type: indirect dependency-group: go_modules - dependency-name: github.com/go-viper/mapstructure/v2 dependency-version: 2.3.0 dependency-type: indirect dependency-group: go_modules - dependency-name: github.com/golang-jwt/jwt/v4 dependency-version: 4.5.2 dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] --- go.mod | 12 ++++++------ go.sum | 25 +++++++++++++------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index f2913c875..d8e2041c5 100644 --- a/go.mod +++ b/go.mod @@ -208,7 +208,7 @@ require ( 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.0 // indirect + github.com/gin-gonic/gin v1.9.1 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect @@ -219,12 +219,12 @@ 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.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.3.0 // indirect github.com/goburrow/cache v0.1.4 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect @@ -294,7 +294,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.2.3 // indirect github.com/openrdap/rdap v0.9.1 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect @@ -329,7 +329,7 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.9 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect github.com/ulikunitz/xz v0.5.12 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect @@ -358,7 +358,7 @@ require ( go.uber.org/zap v1.25.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.39.0 // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/sync v0.15.0 // indirect diff --git a/go.sum b/go.sum index b3d9f81f1..d300e73d0 100644 --- a/go.sum +++ b/go.sum @@ -310,8 +310,8 @@ github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7M github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= -github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= @@ -356,8 +356,8 @@ github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1 github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= 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.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +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/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= @@ -373,8 +373,8 @@ github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= @@ -656,8 +656,8 @@ github.com/openrdap/rdap v0.9.1/go.mod h1:vKSiotbsENrjM/vaHXLddXbW8iQkBfa+ldEuYE github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/ory/dockertest/v3 v3.12.0 h1:3oV9d0sDzlSQfHtIaB5k6ghUCVMVLpAY8hwrqoCyRCw= github.com/ory/dockertest/v3 v3.12.0/go.mod h1:aKNDTva3cp8dwOWwb9cWuX84aH5akkxXRvO7KCwWVjE= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= @@ -812,6 +812,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= @@ -852,8 +853,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= -github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= @@ -958,8 +959,8 @@ go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQP go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= goftp.io/server/v2 v2.0.1 h1:H+9UbCX2N206ePDSVNCjBftOKOgil6kQ5RAQNx5hJwE= goftp.io/server/v2 v2.0.1/go.mod h1:7+H/EIq7tXdfo1Muu5p+l3oQ6rYkDZ8lY7IM5d5kVdQ= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= From a18a386d12e2de275c4330ce042833a02f9d1467 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:00:13 +0700 Subject: [PATCH 046/135] build: downgraded `github.com/zmap/zgrab2` v0.2.0 => v0.1.8 (#6295) Signed-off-by: Dwi Siswanto --- go.mod | 7 +- go.sum | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 230 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index d8e2041c5..dad500870 100644 --- a/go.mod +++ b/go.mod @@ -116,7 +116,7 @@ require ( github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 github.com/trivago/tgo v1.0.7 github.com/yassinebenaid/godump v0.11.1 - github.com/zmap/zgrab2 v0.2.0 + github.com/zmap/zgrab2 v0.1.8 gitlab.com/gitlab-org/api/client-go v0.130.1 go.mongodb.org/mongo-driver v1.17.4 golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b @@ -353,7 +353,7 @@ require ( github.com/zcalusic/sysinfo v1.0.2 // indirect github.com/zeebo/blake3 v0.2.3 // indirect github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect - github.com/zmap/zcrypto v0.0.0-20250324021606-4f0ea0eaccac // indirect + github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // indirect go.etcd.io/bbolt v1.3.10 // indirect go.uber.org/zap v1.25.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect @@ -372,8 +372,5 @@ require ( mellium.im/sasl v0.3.2 // indirect ) -// experimental module replacements that subject to change -replace github.com/zmap/zcrypto v0.0.0-20250324021606-4f0ea0eaccac => github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db - // https://go.dev/ref/mod#go-mod-file-retract retract v3.2.0 // retract due to broken js protocol issue diff --git a/go.sum b/go.sum index d300e73d0..49c200022 100644 --- a/go.sum +++ b/go.sum @@ -8,15 +8,31 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4= code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= @@ -89,12 +105,17 @@ github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbf github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I= +github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= @@ -168,6 +189,9 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= @@ -200,6 +224,9 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= @@ -240,6 +267,7 @@ github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZ github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= @@ -283,7 +311,9 @@ github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= @@ -330,8 +360,18 @@ github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77 github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU= github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= @@ -354,6 +394,7 @@ github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TC github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +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= @@ -370,6 +411,7 @@ github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakr github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= @@ -392,12 +434,26 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -409,7 +465,11 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -427,9 +487,14 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= @@ -509,12 +574,17 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jlaffaye/ftp v0.0.0-20190624084859-c1312a7102bf/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ= @@ -539,7 +609,10 @@ github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -585,6 +658,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/mholt/archives v0.1.3 h1:aEAaOtNra78G+TvV5ohmXrJOAzf++dIlYeDW3N9q458= @@ -615,6 +690,8 @@ github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= @@ -627,6 +704,8 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nwaples/rardecode/v2 v2.1.0 h1:JQl9ZoBPDy+nIZGb1mx8+anfHp/LV3NE2MjMiv0ct/U= github.com/nwaples/rardecode/v2 v2.1.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= @@ -666,6 +745,8 @@ github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -745,7 +826,30 @@ github.com/projectdiscovery/wappalyzergo v0.2.35 h1:4LN5Paa4l5Z5Q5XYwNlF0cRsx1oj github.com/projectdiscovery/wappalyzergo v0.2.35/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +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.0 h1:9JTnze/Md74uS3ZWiRAabityY0un69rOLXsBf8LGgTs= @@ -782,9 +886,12 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= @@ -862,10 +969,13 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= 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.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= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= @@ -883,6 +993,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= @@ -909,7 +1021,9 @@ github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU= github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= @@ -934,10 +1048,12 @@ github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54t github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk= github.com/zmap/zcrypto v0.0.0-20201128221613-3719af1573cf/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ= github.com/zmap/zcrypto v0.0.0-20201211161100-e54a5822fb7e/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ= +github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300/go.mod h1:mOd4yUMgn2fe2nV9KXsa9AyQBFZGzygVPovsZR+Rl5w= github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db h1:IfONOhyZlf4qPt3ENPU+27mBbPjzTQ+swKpj7MJva9I= github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db/go.mod h1:mo/07mo6reDaiz6BzveCuYBWb1d+aX8Pf8Nh+Q57y2g= -github.com/zmap/zgrab2 v0.2.0 h1:j48+zkSw4rbvQOq9em5MnPxwP5QyUmzTXSCtQzZ2MnI= -github.com/zmap/zgrab2 v0.2.0/go.mod h1:vM5eYaxZTjIGZe9oijtxjU4EfucELIr9mbG7Chxmn2I= +github.com/zmap/zflags v1.4.0-beta.1.0.20200204220219-9d95409821b6/go.mod h1:HXDUD+uue8yeLHr0eXx1lvY6CvMiHbTKw5nGmA9OUoo= +github.com/zmap/zgrab2 v0.1.8 h1:PFnXrIBcGjYFec1JNbxMKQuSXXzS+SbqE89luuF4ORY= +github.com/zmap/zgrab2 v0.1.8/go.mod h1:5d8HSmUwvllx4q1qG50v/KXphkg45ZzWdaQtgTFnegE= github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8= gitlab.com/gitlab-org/api/client-go v0.130.1 h1:1xF5C5Zq3sFeNg3PzS2z63oqrxifne3n/OnbI7nptRc= gitlab.com/gitlab-org/api/client-go v0.130.1/go.mod h1:ZhSxLAWadqP6J9lMh40IAZOlOxBLPRh7yFOXR/bMJWM= @@ -949,6 +1065,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -993,7 +1110,9 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -1007,11 +1126,13 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -1024,6 +1145,7 @@ golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1032,19 +1154,34 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -1062,6 +1199,9 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= @@ -1072,7 +1212,10 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -1084,6 +1227,7 @@ golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1095,12 +1239,26 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1108,15 +1266,19 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1163,6 +1325,7 @@ golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1185,13 +1348,29 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= @@ -1211,11 +1390,20 @@ google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1229,17 +1417,50 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= @@ -1257,12 +1478,15 @@ gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -1277,6 +1501,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0= mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY= moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= From 84a76b3d4e720068f185700be964033f761c9c81 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:17:21 +0700 Subject: [PATCH 047/135] version bump --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index bb78cbd07..15d8e9dae 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.6` + Version = `v3.4.7` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From 8304462420c010edea514d3f12f9fa25d179f0ee Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 3 Jul 2025 16:50:21 +0200 Subject: [PATCH 048/135] retain required empty spaces --- pkg/input/formats/yaml/multidoc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/input/formats/yaml/multidoc.go b/pkg/input/formats/yaml/multidoc.go index 1140d5509..3539b07f0 100644 --- a/pkg/input/formats/yaml/multidoc.go +++ b/pkg/input/formats/yaml/multidoc.go @@ -78,7 +78,7 @@ func (j *YamlMultiDocFormat) Parse(input io.Reader, resultsCb formats.ParseReqRe return errors.Wrap(err, "could not decode yaml file") } - raw := strings.TrimSpace(request.Request.Raw) + raw := request.Request.Raw if raw == "" { continue } From 4baf46f080488fda49d18c6b036caf84d928dd3c Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 3 Jul 2025 17:05:14 +0200 Subject: [PATCH 049/135] fixing path --- pkg/input/formats/yaml/multidoc_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go index dd0264b81..1d9c44f2e 100644 --- a/pkg/input/formats/yaml/multidoc_test.go +++ b/pkg/input/formats/yaml/multidoc_test.go @@ -38,7 +38,7 @@ func TestYamlFormatterParse(t *testing.T) { func TestYamlFormatterParseWithVariables(t *testing.T) { format := New() - proxifyYttFile := "../testdata/ginandjuice.ytt.yaml" + proxifyYttFile := "../testdata/ytt/ginandjuice.ytt.yaml" expectedUrls := []string{ "https://ginandjuice.shop/users/3", From cf8d067feaac613edb1f7e956c8bdad06402cfc4 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 3 Jul 2025 17:28:55 +0200 Subject: [PATCH 050/135] fixing test --- pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml | 2 +- pkg/input/formats/yaml/multidoc_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml index b409ad214..b40ece639 100644 --- a/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml +++ b/pkg/input/formats/testdata/ytt/ginandjuice.ytt.yaml @@ -16,7 +16,7 @@ request: raw: |+ POST /users/3 HTTP/1.1 Host: ginandjuice.shop - Authorization: Bearer (@= get_value("token") @) + Authorization: Bearer (@= get_value("token", "3x4mpl3t0k3n") @) Accept-Encoding: gzip Content-Type: application/x-www-form-urlencoded Connection: close diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go index 1d9c44f2e..54efe0326 100644 --- a/pkg/input/formats/yaml/multidoc_test.go +++ b/pkg/input/formats/yaml/multidoc_test.go @@ -66,7 +66,7 @@ Content-Type: application/x-www-form-urlencoded Connection: close User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 -foo=catalog&bar=product` +foo="catalog"&bar=product&debug=false` normalised := strings.ReplaceAll(request.Request.Raw, "\r\n", "\n") require.Equal(t, expectedRaw, strings.TrimSuffix(normalised, "\n"), "request raw does not match expected value") From d55ab2f82783a7cfe222a798d1973a7783d22e5c Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 3 Jul 2025 18:05:08 +0200 Subject: [PATCH 051/135] use bytes slice --- pkg/input/formats/yaml/multidoc.go | 11 +++-------- pkg/input/formats/yaml/ytt.go | 11 ++--------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/pkg/input/formats/yaml/multidoc.go b/pkg/input/formats/yaml/multidoc.go index 3539b07f0..a77375c77 100644 --- a/pkg/input/formats/yaml/multidoc.go +++ b/pkg/input/formats/yaml/multidoc.go @@ -1,8 +1,8 @@ package yaml import ( + "bytes" "io" - "strings" "github.com/pkg/errors" "github.com/projectdiscovery/gologger" @@ -56,16 +56,11 @@ func (j *YamlMultiDocFormat) Parse(input io.Reader, resultsCb formats.ParseReqRe } tpl := []string{string(data)} dvs := mapToKeyValueSlice(j.opts.Variables) - finalInput, err = ytt(tpl, dvs, j.opts.VarsFilePaths) + finalData, err := ytt(tpl, dvs, j.opts.VarsFilePaths) if err != nil { return errors.Wrap(err, "could not apply ytt templating") } - finalData, err := io.ReadAll(finalInput) - if err != nil { - return errors.Wrap(err, "could not read templated input") - } - finalInput = strings.NewReader(string(finalData)) - + finalInput = bytes.NewReader(finalData) } decoder := YamlUtil.NewDecoder(finalInput) diff --git a/pkg/input/formats/yaml/ytt.go b/pkg/input/formats/yaml/ytt.go index 3ccf5f6d2..faaf6ccdc 100644 --- a/pkg/input/formats/yaml/ytt.go +++ b/pkg/input/formats/yaml/ytt.go @@ -1,9 +1,7 @@ package yaml import ( - "bytes" "fmt" - "io" "strings" yttcmd "carvel.dev/ytt/pkg/cmd/template" @@ -12,7 +10,7 @@ import ( "gopkg.in/yaml.v2" ) -func ytt(tpl, dvs []string, varFiles []string) (io.Reader, error) { +func ytt(tpl, dvs []string, varFiles []string) ([]byte, error) { // create and invoke ytt "template" command templatingOptions := yttcmd.NewOptions() @@ -38,12 +36,7 @@ func ytt(tpl, dvs []string, varFiles []string) (io.Reader, error) { return nil, output.Err } - // output.DocSet contains the full set of resulting YAML documents, in order. - bs, err := output.DocSet.AsBytes() - if err != nil { - return nil, err - } - return bytes.NewReader(bs), nil + return output.DocSet.AsBytes() } // templatesAsInput conveniently wraps one or more strings, each in a files.File, into a template.Input. From eccd90d53c1da6a7e8e554dc296c596a451ff51a Mon Sep 17 00:00:00 2001 From: alban-stourbe-wmx <159776828+alban-stourbe-wmx@users.noreply.github.com> Date: Fri, 4 Jul 2025 16:51:09 +0200 Subject: [PATCH 052/135] fix(headless): Variables are now available into headless template (#6301) * fix(headless): variables now available into simple headless template * chore: erase debug logs --- pkg/protocols/headless/request.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/protocols/headless/request.go b/pkg/protocols/headless/request.go index afe03c711..5e508c02b 100644 --- a/pkg/protocols/headless/request.go +++ b/pkg/protocols/headless/request.go @@ -54,10 +54,11 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, optionVars := generators.BuildPayloadFromOptions(request.options.Options) // add templatecontext variables to varMap if request.options.HasTemplateCtx(input.MetaInput) { - vars = generators.MergeMaps(vars, metadata, optionVars, request.options.GetTemplateCtx(input.MetaInput).GetAll()) + vars = generators.MergeMaps(vars, request.options.GetTemplateCtx(input.MetaInput).GetAll()) } + variablesMap := request.options.Variables.Evaluate(vars) - vars = generators.MergeMaps(vars, variablesMap, request.options.Constants) + vars = generators.MergeMaps(vars, metadata, optionVars, variablesMap, request.options.Constants) // check for operator matches by wrapping callback gotmatches := false @@ -118,8 +119,8 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p return errors.Wrap(err, errCouldNotGetHtmlElement) } defer func() { - _ = instance.Close() - }() + _ = instance.Close() + }() instance.SetInteractsh(request.options.Interactsh) From 87de71dee9d1df36df3f118041eea11624695d35 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 7 Jul 2025 18:12:50 +0200 Subject: [PATCH 053/135] bumping version + memory cleanup --- go.mod | 6 ++++-- go.sum | 8 ++++++++ pkg/installer/template.go | 9 ++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index dad500870..58a04a974 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/julienschmidt/httprouter v1.3.0 github.com/logrusorgru/aurora v2.0.3+incompatible github.com/miekg/dns v1.1.66 - github.com/olekukonko/tablewriter v0.0.5 + 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.1 @@ -201,7 +201,7 @@ require ( 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 - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.18.0 // indirect 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 @@ -290,6 +290,8 @@ require ( github.com/nwaples/rardecode/v2 v2.1.0 // indirect github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.2.3 // indirect diff --git a/go.sum b/go.sum index 49c200022..0d9a10ddb 100644 --- a/go.sum +++ b/go.sum @@ -317,6 +317,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= @@ -714,8 +716,14 @@ github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//J github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ= +github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= diff --git a/pkg/installer/template.go b/pkg/installer/template.go index 26d09f9f2..4ee784477 100644 --- a/pkg/installer/template.go +++ b/pkg/installer/template.go @@ -53,11 +53,14 @@ func (t *templateUpdateResults) String() string { }, } table := tablewriter.NewWriter(&buff) - table.SetHeader([]string{"Total", "Added", "Modified", "Removed"}) + table.Header("Total", "Added", "Modified", "Removed") for _, v := range data { - table.Append(v) + _ = table.Append(v) } - table.Render() + _ = table.Render() + defer func() { + _ = table.Close() + }() return buff.String() } From bd5864dbb58f37de2b98c32af90fa36d770f8f6b Mon Sep 17 00:00:00 2001 From: Dwi Siswanto Date: Tue, 8 Jul 2025 17:35:55 +0700 Subject: [PATCH 054/135] chore(config): rm deprecated codes and calls Signed-off-by: Dwi Siswanto --- pkg/catalog/config/nucleiconfig.go | 67 +----------------------------- 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/pkg/catalog/config/nucleiconfig.go b/pkg/catalog/config/nucleiconfig.go index 246870935..ebfbb77a3 100644 --- a/pkg/catalog/config/nucleiconfig.go +++ b/pkg/catalog/config/nucleiconfig.go @@ -4,13 +4,11 @@ import ( "bytes" "crypto/md5" "fmt" - "log" "os" "path/filepath" "slices" "strings" - "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" "github.com/projectdiscovery/utils/env" @@ -367,9 +365,6 @@ func (c *Config) parseDebugArgs(data string) { } func init() { - // first attempt to migrate all files from old config directory to new config directory - goflags.AttemptConfigMigration() // regardless how many times this is called it will only migrate once based on condition - ConfigDir := folderutil.AppConfigDirOrDefault(FallbackConfigFolderName, BinaryName) if cfgDir := os.Getenv(NucleiConfigDirEnv); cfgDir != "" { @@ -406,9 +401,7 @@ func init() { gologger.Error().Msgf("failed to write config file at %s got: %s", DefaultConfig.getTemplatesConfigFilePath(), err) } } - // attempt to migrate resume files - // this also happens once regardless of how many times this is called - migrateResumeFiles() + // Loads/updates paths of custom templates // Note: custom templates paths should not be updated in config file // and even if it is changed we don't follow it since it is not expected behavior @@ -423,61 +416,3 @@ func applyDefaultConfig() { // updates all necessary paths DefaultConfig.SetTemplatesDir(DefaultConfig.TemplatesDirectory) } - -func migrateResumeFiles() { - // attempt to migrate old resume files to new directory structure - // after migration has been done in goflags - oldResumeDir := DefaultConfig.GetConfigDir() - // migrate old resume file to new directory structure - if !fileutil.FileOrFolderExists(DefaultConfig.GetCacheDir()) && fileutil.FileOrFolderExists(oldResumeDir) { - // this means new cache dir doesn't exist, so we need to migrate - // first check if old resume file exists if not then no need to migrate - exists := false - files, err := os.ReadDir(oldResumeDir) - if err != nil { - // log silently - log.Printf("could not read old resume dir: %s\n", err) - return - } - for _, file := range files { - if strings.HasSuffix(file.Name(), ".cfg") { - exists = true - break - } - } - if !exists { - // no need to migrate - return - } - - // create new cache dir - err = os.MkdirAll(DefaultConfig.GetCacheDir(), os.ModePerm) - if err != nil { - // log silently - log.Printf("could not create new cache dir: %s\n", err) - return - } - err = filepath.WalkDir(oldResumeDir, func(path string, d os.DirEntry, err error) error { - if err != nil { - return err - } - if d.IsDir() { - return nil - } - if !strings.HasSuffix(path, ".cfg") { - return nil - } - err = os.Rename(path, filepath.Join(DefaultConfig.GetCacheDir(), filepath.Base(path))) - if err != nil { - return err - } - return nil - }) - if err != nil { - // log silently - log.Printf("could not migrate old resume files: %s\n", err) - return - } - - } -} From b756b2706ffaddda3bddad7fcc4197ec0c334a47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 17:57:09 +0700 Subject: [PATCH 055/135] 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] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 58a04a974..2d3cb8e10 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/projectdiscovery/interactsh v1.2.4 github.com/projectdiscovery/rawhttp v0.1.90 github.com/projectdiscovery/retryabledns v1.0.103 - github.com/projectdiscovery/retryablehttp-go v1.0.116 + 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 @@ -108,7 +108,7 @@ require ( github.com/projectdiscovery/uncover v1.1.0 github.com/projectdiscovery/useragent v0.0.101 github.com/projectdiscovery/utils v0.4.21 - github.com/projectdiscovery/wappalyzergo v0.2.35 + github.com/projectdiscovery/wappalyzergo v0.2.36 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -305,7 +305,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.15 // indirect + github.com/projectdiscovery/cdncheck v1.1.26 // indirect 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 diff --git a/go.sum b/go.sum index 0d9a10ddb..11c9848e2 100644 --- a/go.sum +++ b/go.sum @@ -768,8 +768,8 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.15 h1:rRs3LW2MP7V8QeONVRYce6RhDcWp83O+AWmt+QQ4mBM= -github.com/projectdiscovery/cdncheck v1.1.15/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.26 h1:R6JxzU3ptGNrzzvS261xHWssDt9GlOCWXkuet1huOyA= +github.com/projectdiscovery/cdncheck v1.1.26/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= github.com/projectdiscovery/dsl v0.5.0 h1:3HHY14FNmdwWXq3pi9dd8JjUHQzskZjLD/pZKVx5Vi4= @@ -816,8 +816,8 @@ github.com/projectdiscovery/rdap v0.9.0 h1:wPhHx5pQ2QI+WGhyNb2PjhTl0NtB39Nk7YFZ9 github.com/projectdiscovery/rdap v0.9.0/go.mod h1:zk4yrJFQ2Hy36Aqk+DvotYQxYAeALaCJ5ORySkff36Q= 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.116 h1:yjgT5q6lGkZ7gkuuHe5wm2mmq9tE5t23PSk6sz3F6/E= -github.com/projectdiscovery/retryablehttp-go v1.0.116/go.mod h1:GUMjLgc9hJtIzx34igabPtem98ewhq2xEG8TZmhefog= +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= @@ -830,8 +830,8 @@ github.com/projectdiscovery/useragent v0.0.101 h1:8A+XOJ/nIH+WqW8ogLxJ/psemGp8AT github.com/projectdiscovery/useragent v0.0.101/go.mod h1:RGoRw1BQ/lJnhYMbMpEKjyAAgCaDCr/+GsULo5yEJ2I= 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.35 h1:4LN5Paa4l5Z5Q5XYwNlF0cRsx1ojYeY5EELEMpk8grw= -github.com/projectdiscovery/wappalyzergo v0.2.35/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA= +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= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= From 7e2ec686ae7b09e2bc45e03d67421413929c9b0b Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Wed, 9 Jul 2025 01:04:16 +0700 Subject: [PATCH 056/135] fix(lib): scans didn't stop on ctx cancellation (#6310) * fix(lib): scans didn't stop on ctx cancellation Signed-off-by: Dwi Siswanto * 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 --------- Signed-off-by: Dwi Siswanto Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- lib/sdk.go | 42 ++++++++++++++++++++++++++++++++++++------ lib/sdk_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 lib/sdk_test.go diff --git a/lib/sdk.go b/lib/sdk.go index 7f2ec5bcc..a8639b1d6 100644 --- a/lib/sdk.go +++ b/lib/sdk.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "io" + "sync" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" @@ -64,6 +65,7 @@ type NucleiEngine struct { templatesLoaded bool // unexported core fields + ctx context.Context interactshClient *interactsh.Client catalog catalog.Catalog rateLimiter *ratelimit.Limiter @@ -246,9 +248,9 @@ func (e *NucleiEngine) ExecuteCallbackWithCtx(ctx context.Context, callback ...f } filtered := []func(event *output.ResultEvent){} - for _, callback := range callback { - if callback != nil { - filtered = append(filtered, callback) + for _, cb := range callback { + if cb != nil { + filtered = append(filtered, cb) } } e.resultCallbacks = append(e.resultCallbacks, filtered...) @@ -258,15 +260,32 @@ func (e *NucleiEngine) ExecuteCallbackWithCtx(ctx context.Context, callback ...f return ErrNoTemplatesAvailable } - _ = e.engine.ExecuteScanWithOpts(ctx, templatesAndWorkflows, e.inputProvider, false) - defer e.engine.WorkPool().Wait() + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + _ = e.engine.ExecuteScanWithOpts(ctx, templatesAndWorkflows, e.inputProvider, false) + }() + + // wait for context to be cancelled + select { + case <-ctx.Done(): + <-wait(&wg) // wait for scan to finish + return ctx.Err() + case <-wait(&wg): + // scan finished + } return nil } // ExecuteWithCallback is same as ExecuteCallbackWithCtx but with default context // Note this is deprecated and will be removed in future major release func (e *NucleiEngine) ExecuteWithCallback(callback ...func(event *output.ResultEvent)) error { - return e.ExecuteCallbackWithCtx(context.Background(), callback...) + ctx := context.Background() + if e.ctx != nil { + ctx = e.ctx + } + return e.ExecuteCallbackWithCtx(ctx, callback...) } // Options return nuclei Type Options @@ -290,6 +309,7 @@ func NewNucleiEngineCtx(ctx context.Context, options ...NucleiSDKOptions) (*Nucl e := &NucleiEngine{ opts: types.DefaultOptions(), mode: singleInstance, + ctx: ctx, } for _, option := range options { if err := option(e); err != nil { @@ -306,3 +326,13 @@ func NewNucleiEngineCtx(ctx context.Context, options ...NucleiSDKOptions) (*Nucl func NewNucleiEngine(options ...NucleiSDKOptions) (*NucleiEngine, error) { return NewNucleiEngineCtx(context.Background(), options...) } + +// wait for a waitgroup to finish +func wait(wg *sync.WaitGroup) <-chan struct{} { + ch := make(chan struct{}) + go func() { + defer close(ch) + wg.Wait() + }() + return ch +} diff --git a/lib/sdk_test.go b/lib/sdk_test.go new file mode 100644 index 000000000..c86f8ebbf --- /dev/null +++ b/lib/sdk_test.go @@ -0,0 +1,37 @@ +package nuclei_test + +import ( + "context" + "log" + "testing" + "time" + + nuclei "github.com/projectdiscovery/nuclei/v3/lib" + "github.com/stretchr/testify/require" +) + +func TestContextCancelNucleiEngine(t *testing.T) { + // create nuclei engine with options + ctx, cancel := context.WithCancel(context.Background()) + ne, err := nuclei.NewNucleiEngineCtx(ctx, + nuclei.WithTemplateFilters(nuclei.TemplateFilters{Tags: []string{"oast"}}), + nuclei.EnableStatsWithOpts(nuclei.StatsOptions{MetricServerPort: 0}), + ) + require.NoError(t, err, "could not create nuclei engine") + + go func() { + time.Sleep(time.Second * 2) + cancel() + log.Println("Test: context cancelled") + }() + + // load targets and optionally probe non http/https targets + ne.LoadTargets([]string{"http://honey.scanme.sh"}, false) + // when callback is nil it nuclei will print JSON output to stdout + err = ne.ExecuteWithCallback(nil) + if err != nil { + // we expect a context cancellation error + require.ErrorIs(t, err, context.Canceled, "was expecting context cancellation error") + } + defer ne.Close() +} From 285c5e14426e684e05fe17a721e0a8da3a1b0a58 Mon Sep 17 00:00:00 2001 From: Jose De La O Hernandez Date: Tue, 8 Jul 2025 19:04:05 -0400 Subject: [PATCH 057/135] fixing panic caused by uninitialized colorizer (#6315) --- lib/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/config.go b/lib/config.go index f570a0729..c7746c090 100644 --- a/lib/config.go +++ b/lib/config.go @@ -296,8 +296,8 @@ func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions { if e.opts.ShouldUseHostError() { maxHostError := opts.MaxHostError if e.opts.TemplateThreads > maxHostError { - gologger.Print().Msgf("[%v] The concurrency value is higher than max-host-error", e.executerOpts.Colorizer.BrightYellow("WRN")) - gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", e.opts.TemplateThreads) + gologger.Warning().Msg(" The concurrency value is higher than max-host-error") + gologger.Warning().Msgf("Adjusting max-host-error to the concurrency value: %d", e.opts.TemplateThreads) maxHostError = e.opts.TemplateThreads e.opts.MaxHostError = maxHostError } From f26996cb8900a4614cacf91d7d26af5141151eeb Mon Sep 17 00:00:00 2001 From: HD Moore Date: Wed, 9 Jul 2025 14:47:26 -0500 Subject: [PATCH 058/135] 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 * Revert "disable upload" This reverts commit 114fbe6663361bf41cf8b2645fd2d57083d53682. * Revert "hardcoding path" This reverts commit cf12ca800e0a0e974bd9fd4826a24e51547f7c00. --------- Signed-off-by: Dwi Siswanto Co-authored-by: Mzack9999 Co-authored-by: Dwi Siswanto Co-authored-by: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> --- .github/workflows/tests.yaml | 8 +- cmd/functional-test/main.go | 4 +- cmd/integration-test/headless.go | 8 +- cmd/integration-test/http.go | 16 +- cmd/integration-test/integration-test.go | 27 +- cmd/integration-test/library.go | 14 +- cmd/integration-test/network.go | 24 +- cmd/integration-test/profile-loader.go | 6 +- cmd/nuclei/main.go | 135 +++++----- cmd/nuclei/main_benchmark_test.go | 3 +- cmd/tmc/main.go | 6 +- cmd/tools/signer/main.go | 4 +- go.mod | 62 +++-- go.sum | 30 +-- internal/pdcp/writer.go | 28 +- internal/runner/inputs.go | 16 +- internal/runner/lazy.go | 6 +- internal/runner/options.go | 56 ++-- internal/runner/proxy.go | 9 +- internal/runner/runner.go | 122 +++++---- internal/runner/templates.go | 21 +- internal/server/nuclei_sdk.go | 10 +- internal/server/server.go | 2 +- lib/config.go | 37 ++- lib/multi.go | 17 +- lib/sdk.go | 30 ++- lib/sdk_private.go | 39 ++- pkg/catalog/config/ignorefile.go | 3 +- pkg/catalog/config/nucleiconfig.go | 27 +- pkg/catalog/config/template.go | 7 +- pkg/catalog/disk/find.go | 5 +- pkg/catalog/loader/ai_loader.go | 7 +- pkg/catalog/loader/loader.go | 75 +++--- pkg/catalog/loader/remote_loader.go | 83 +++--- pkg/core/engine.go | 9 +- pkg/core/execute_options.go | 3 +- pkg/core/executors.go | 13 +- pkg/fuzz/analyzers/time/time_delay.go | 1 - pkg/fuzz/dataformat/multipart.go | 4 +- pkg/input/provider/http/multiformat.go | 6 +- pkg/input/provider/interface.go | 6 +- pkg/input/provider/list/hmap.go | 68 +++-- pkg/input/provider/list/hmap_test.go | 6 +- pkg/input/provider/simple.go | 10 +- pkg/js/compiler/compiler.go | 5 +- pkg/js/compiler/init.go | 5 + pkg/js/compiler/non-pool.go | 2 +- pkg/js/compiler/pool.go | 12 +- pkg/js/devtools/bindgen/output.go | 4 +- .../devtools/bindgen/templates/go_class.tmpl | 2 +- pkg/js/generated/go/libbytes/bytes.go | 2 +- pkg/js/generated/go/libfs/fs.go | 2 +- pkg/js/generated/go/libgoconsole/goconsole.go | 2 +- pkg/js/generated/go/libikev2/ikev2.go | 2 +- pkg/js/generated/go/libkerberos/kerberos.go | 2 +- pkg/js/generated/go/libldap/ldap.go | 2 +- pkg/js/generated/go/libmssql/mssql.go | 2 +- pkg/js/generated/go/libmysql/mysql.go | 2 +- pkg/js/generated/go/libnet/net.go | 2 +- pkg/js/generated/go/liboracle/oracle.go | 2 +- pkg/js/generated/go/libpop3/pop3.go | 2 +- pkg/js/generated/go/libpostgres/postgres.go | 2 +- pkg/js/generated/go/librdp/rdp.go | 2 +- pkg/js/generated/go/libredis/redis.go | 2 +- pkg/js/generated/go/librsync/rsync.go | 2 +- pkg/js/generated/go/libsmb/smb.go | 2 +- pkg/js/generated/go/libsmtp/smtp.go | 2 +- pkg/js/generated/go/libssh/ssh.go | 2 +- pkg/js/generated/go/libstructs/structs.go | 2 +- pkg/js/generated/go/libtelnet/telnet.go | 2 +- pkg/js/generated/go/libvnc/vnc.go | 2 +- pkg/js/global/helpers.go | 2 +- pkg/js/global/scripts.go | 26 +- pkg/js/global/scripts_test.go | 6 +- pkg/js/gojs/gojs.go | 62 ++++- pkg/js/gojs/set.go | 62 ++++- pkg/js/libs/bytes/buffer.go | 2 +- pkg/js/libs/goconsole/log.go | 2 +- pkg/js/libs/kerberos/kerberosx.go | 13 +- pkg/js/libs/kerberos/sendtokdc.go | 31 ++- pkg/js/libs/ldap/ldap.go | 16 +- pkg/js/libs/mssql/memo.mssql.go | 8 +- pkg/js/libs/mssql/mssql.go | 49 ++-- pkg/js/libs/mysql/memo.mysql.go | 8 +- pkg/js/libs/mysql/mysql.go | 68 +++-- pkg/js/libs/mysql/mysql_private.go | 4 +- pkg/js/libs/net/net.go | 19 +- pkg/js/libs/oracle/memo.oracle.go | 4 +- pkg/js/libs/oracle/oracle.go | 15 +- pkg/js/libs/pop3/memo.pop3.go | 4 +- pkg/js/libs/pop3/pop3.go | 15 +- pkg/js/libs/postgres/memo.postgres.go | 12 +- pkg/js/libs/postgres/postgres.go | 66 +++-- pkg/js/libs/rdp/memo.rdp.go | 8 +- pkg/js/libs/rdp/rdp.go | 35 ++- pkg/js/libs/redis/memo.redis.go | 16 +- pkg/js/libs/redis/redis.go | 66 +++-- pkg/js/libs/rsync/memo.rsync.go | 4 +- pkg/js/libs/rsync/rsync.go | 14 +- pkg/js/libs/smb/memo.smb.go | 8 +- pkg/js/libs/smb/memo.smb_private.go | 4 +- pkg/js/libs/smb/memo.smbghost.go | 4 +- pkg/js/libs/smb/smb.go | 48 ++-- pkg/js/libs/smb/smb_private.go | 13 +- pkg/js/libs/smb/smbghost.go | 16 +- pkg/js/libs/smtp/smtp.go | 31 ++- pkg/js/libs/ssh/ssh.go | 56 ++-- pkg/js/libs/telnet/memo.telnet.go | 4 +- pkg/js/libs/telnet/telnet.go | 15 +- pkg/js/libs/vnc/memo.vnc.go | 4 +- pkg/js/libs/vnc/vnc.go | 14 +- pkg/js/utils/nucleijs.go | 10 +- pkg/js/utils/pgwrap/pgwrap.go | 35 ++- pkg/protocols/code/code.go | 8 +- pkg/protocols/code/helpers.go | 2 +- .../common/automaticscan/automaticscan.go | 6 +- pkg/protocols/common/automaticscan/util.go | 5 +- pkg/protocols/common/interactsh/options.go | 3 + pkg/protocols/common/protocolinit/init.go | 4 +- pkg/protocols/common/protocolstate/context.go | 46 ++++ pkg/protocols/common/protocolstate/dialers.go | 23 ++ pkg/protocols/common/protocolstate/file.go | 12 +- .../common/protocolstate/headless.go | 98 +++++-- pkg/protocols/common/protocolstate/js.go | 4 +- pkg/protocols/common/protocolstate/state.go | 93 +++++-- pkg/protocols/dns/dns.go | 5 + pkg/protocols/dns/operators.go | 2 +- pkg/protocols/file/file.go | 5 + pkg/protocols/file/request.go | 12 +- pkg/protocols/headless/engine/engine.go | 18 +- pkg/protocols/headless/engine/http_client.go | 15 +- pkg/protocols/headless/engine/page.go | 4 +- pkg/protocols/headless/engine/page_actions.go | 4 +- .../headless/engine/page_actions_test.go | 14 +- pkg/protocols/headless/engine/rules.go | 2 +- pkg/protocols/headless/headless.go | 5 + pkg/protocols/headless/request.go | 4 +- pkg/protocols/http/cluster.go | 3 +- pkg/protocols/http/http.go | 5 + .../http/httpclientpool/clientpool.go | 78 +++--- pkg/protocols/http/race/syncedreadcloser.go | 4 +- pkg/protocols/http/request.go | 11 +- .../http/request_annotations_test.go | 4 +- pkg/protocols/http/request_fuzz.go | 2 +- pkg/protocols/http/request_test.go | 4 +- pkg/protocols/http/signerpool/signerpool.go | 8 +- pkg/protocols/javascript/js.go | 19 +- pkg/protocols/javascript/js_test.go | 6 +- pkg/protocols/network/network.go | 9 + .../network/networkclientpool/clientpool.go | 19 +- pkg/protocols/network/request.go | 4 +- pkg/protocols/offlinehttp/request.go | 9 +- pkg/protocols/protocols.go | 83 +++++- pkg/protocols/ssl/ssl.go | 8 +- pkg/protocols/websocket/websocket.go | 9 +- .../whois/rdapclientpool/clientpool.go | 8 + pkg/protocols/whois/whois.go | 5 + pkg/reporting/exporters/es/elasticsearch.go | 16 +- pkg/reporting/exporters/splunk/splunkhec.go | 12 +- pkg/reporting/options.go | 2 + pkg/reporting/reporting.go | 6 +- pkg/reporting/trackers/linear/linear.go | 4 +- pkg/scan/charts/charts.go | 4 +- pkg/scan/charts/echarts.go | 8 +- pkg/templates/cluster.go | 4 +- pkg/templates/compile.go | 96 ++++++- pkg/templates/compile_test.go | 24 +- pkg/templates/parser.go | 99 ++++++- pkg/templates/template_sign.go | 2 +- pkg/testutils/fuzzplayground/db.go | 4 +- pkg/testutils/fuzzplayground/server.go | 12 +- pkg/testutils/integration.go | 4 +- pkg/tmplexec/exec.go | 2 +- pkg/tmplexec/flow/builtin/dedupe.go | 2 +- pkg/tmplexec/flow/flow_executor.go | 10 +- pkg/tmplexec/flow/flow_executor_test.go | 6 +- pkg/tmplexec/flow/flow_internal.go | 4 +- pkg/tmplexec/flow/vm.go | 2 +- pkg/tmplexec/multiproto/multi_test.go | 6 +- pkg/types/types.go | 243 ++++++++++++++++++ 180 files changed, 2274 insertions(+), 1034 deletions(-) create mode 100644 pkg/protocols/common/protocolstate/context.go create mode 100644 pkg/protocols/common/protocolstate/dialers.go diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 7cbfd2f12..dce907afb 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -59,9 +59,11 @@ jobs: working-directory: examples/simple/ # - run: go run . # Temporarily disabled very flaky in github actions # working-directory: examples/advanced/ - - name: "with Speed Control" - run: go run . - working-directory: examples/with_speed_control/ + + # TODO: FIX with ExecutionID (ref: https://github.com/projectdiscovery/nuclei/pull/6296) + # - name: "with Speed Control" + # run: go run . + # working-directory: examples/with_speed_control/ integration: name: "Integration tests" diff --git a/cmd/functional-test/main.go b/cmd/functional-test/main.go index 9e605522f..caab15f2a 100644 --- a/cmd/functional-test/main.go +++ b/cmd/functional-test/main.go @@ -42,8 +42,8 @@ func runFunctionalTests(debug bool) (error, bool) { return errors.Wrap(err, "could not open test cases"), true } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() errored, failedTestCases := runTestCases(file, debug) diff --git a/cmd/integration-test/headless.go b/cmd/integration-test/headless.go index 04ccd295d..abc2a0368 100644 --- a/cmd/integration-test/headless.go +++ b/cmd/integration-test/headless.go @@ -179,8 +179,8 @@ func (h *headlessFileUpload) Execute(filePath string) error { } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() content, err := io.ReadAll(file) if err != nil { @@ -238,8 +238,8 @@ func (h *headlessFileUploadNegative) Execute(filePath string) error { } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() content, err := io.ReadAll(file) if err != nil { diff --git a/cmd/integration-test/http.go b/cmd/integration-test/http.go index 315f90218..2d273d513 100644 --- a/cmd/integration-test/http.go +++ b/cmd/integration-test/http.go @@ -948,8 +948,8 @@ func (h *httpRequestSelfContained) Execute(filePath string) error { _ = server.ListenAndServe() }() defer func() { - _ = server.Close() - }() + _ = server.Close() + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc") if err != nil { @@ -986,8 +986,8 @@ func (h *httpRequestSelfContainedWithParams) Execute(filePath string) error { _ = server.ListenAndServe() }() defer func() { - _ = server.Close() - }() + _ = server.Close() + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-esc") if err != nil { @@ -1021,8 +1021,8 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error { _ = server.ListenAndServe() }() defer func() { - _ = server.Close() - }() + _ = server.Close() + }() // create temp file FileLoc, err := os.CreateTemp("", "self-contained-payload-*.txt") @@ -1033,8 +1033,8 @@ func (h *httpRequestSelfContainedFileInput) Execute(filePath string) error { return errorutil.NewWithErr(err).Msgf("failed to write payload to temp file") } defer func() { - _ = FileLoc.Close() - }() + _ = FileLoc.Close() + }() results, err := testutils.RunNucleiTemplateAndGetResults(filePath, "", debug, "-V", "test="+FileLoc.Name(), "-esc") if err != nil { diff --git a/cmd/integration-test/integration-test.go b/cmd/integration-test/integration-test.go index 160dd13e1..545d5da41 100644 --- a/cmd/integration-test/integration-test.go +++ b/cmd/integration-test/integration-test.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "os" + "regexp" "runtime" "strings" @@ -90,8 +91,8 @@ func main() { defer fuzzplayground.Cleanup() server := fuzzplayground.GetPlaygroundServer() defer func() { - _ = server.Close() - }() + _ = server.Close() + }() go func() { if err := server.Start("localhost:8082"); err != nil { if !strings.Contains(err.Error(), "Server closed") { @@ -210,7 +211,7 @@ func execute(testCase testutils.TestCase, templatePath string) (string, error) { } func expectResultsCount(results []string, expectedNumbers ...int) error { - results = filterHeadlessLogs(results) + results = filterLines(results) match := sliceutil.Contains(expectedNumbers, len(results)) if !match { return fmt.Errorf("incorrect number of results: %d (actual) vs %v (expected) \nResults:\n\t%s\n", len(results), expectedNumbers, strings.Join(results, "\n\t")) // nolint:all @@ -224,6 +225,13 @@ func normalizeSplit(str string) []string { }) } +// filterLines applies all filtering functions to the results +func filterLines(results []string) []string { + results = filterHeadlessLogs(results) + results = filterUnsignedTemplatesWarnings(results) + return results +} + // if chromium is not installed go-rod installs it in .cache directory // this function filters out the logs from download and installation func filterHeadlessLogs(results []string) []string { @@ -237,3 +245,16 @@ func filterHeadlessLogs(results []string) []string { } return filtered } + +// filterUnsignedTemplatesWarnings filters out warning messages about unsigned templates +func filterUnsignedTemplatesWarnings(results []string) []string { + filtered := []string{} + unsignedTemplatesRegex := regexp.MustCompile(`Loading \d+ unsigned templates for scan\. Use with caution\.`) + for _, result := range results { + if unsignedTemplatesRegex.MatchString(result) { + continue + } + filtered = append(filtered, result) + } + return filtered +} diff --git a/cmd/integration-test/library.go b/cmd/integration-test/library.go index 22f7f4ac0..3513b1d04 100644 --- a/cmd/integration-test/library.go +++ b/cmd/integration-test/library.go @@ -68,17 +68,21 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error) cache := hosterrorscache.New(30, hosterrorscache.DefaultMaxHostsCount, nil) defer cache.Close() + defaultOpts := types.DefaultOptions() + defaultOpts.ExecutionId = "test" + mockProgress := &testutils.MockProgressClient{} - reportingClient, err := reporting.New(&reporting.Options{}, "", false) + reportingClient, err := reporting.New(&reporting.Options{ExecutionId: defaultOpts.ExecutionId}, "", false) if err != nil { return nil, err } defer reportingClient.Close() - defaultOpts := types.DefaultOptions() _ = protocolstate.Init(defaultOpts) _ = protocolinit.Init(defaultOpts) + defer protocolstate.Close(defaultOpts.ExecutionId) + defaultOpts.Templates = goflags.StringSlice{templatePath} defaultOpts.ExcludeTags = config.ReadIgnoreFile().Tags @@ -100,7 +104,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error) ratelimiter := ratelimit.New(context.Background(), 150, time.Second) defer ratelimiter.Stop() - executerOpts := protocols.ExecutorOptions{ + executerOpts := &protocols.ExecutorOptions{ Output: outputWriter, Options: defaultOpts, Progress: mockProgress, @@ -116,7 +120,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error) engine := core.New(defaultOpts) engine.SetExecuterOptions(executerOpts) - workflowLoader, err := parsers.NewLoader(&executerOpts) + workflowLoader, err := parsers.NewLoader(executerOpts) if err != nil { log.Fatalf("Could not create workflow loader: %s\n", err) } @@ -128,7 +132,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error) } store.Load() - _ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL)) + _ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(defaultOpts.ExecutionId, templateURL)) engine.WorkPool().Wait() // Wait for the scan to finish return results, nil diff --git a/cmd/integration-test/network.go b/cmd/integration-test/network.go index 1fb1fe709..3cfe331a8 100644 --- a/cmd/integration-test/network.go +++ b/cmd/integration-test/network.go @@ -34,8 +34,8 @@ func (h *networkBasic) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { @@ -71,8 +71,8 @@ func (h *networkMultiStep) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 5, time.Duration(5)*time.Second) if err != nil { @@ -119,8 +119,8 @@ type networkRequestSelContained struct{} func (h *networkRequestSelContained) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() _, _ = conn.Write([]byte("Authentication successful")) }) @@ -141,8 +141,8 @@ func (h *networkVariables) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, defaultStaticPort, func(conn net.Conn) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { @@ -171,8 +171,8 @@ type networkPort struct{} func (n *networkPort) Execute(filePath string) error { ts := testutils.NewTCPServer(nil, 23846, func(conn net.Conn) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { @@ -206,8 +206,8 @@ func (n *networkPort) Execute(filePath string) error { // this is positive test case where we expect port to be overridden and 34567 to be used ts2 := testutils.NewTCPServer(nil, 34567, func(conn net.Conn) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() data, err := reader.ConnReadNWithTimeout(conn, 4, time.Duration(5)*time.Second) if err != nil { diff --git a/cmd/integration-test/profile-loader.go b/cmd/integration-test/profile-loader.go index dafc15aa2..80ae4cfd4 100644 --- a/cmd/integration-test/profile-loader.go +++ b/cmd/integration-test/profile-loader.go @@ -16,7 +16,7 @@ var profileLoaderTestcases = []TestCaseInfo{ type profileLoaderByRelFile struct{} func (h *profileLoaderByRelFile) Execute(testName string) error { - results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", "cloud.yml") + results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", "cloud.yml") if err != nil { return errorutil.NewWithErr(err).Msgf("failed to load template with id") } @@ -29,7 +29,7 @@ func (h *profileLoaderByRelFile) Execute(testName string) error { type profileLoaderById struct{} func (h *profileLoaderById) Execute(testName string) error { - results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", "cloud") + results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", "cloud") if err != nil { return errorutil.NewWithErr(err).Msgf("failed to load template with id") } @@ -43,7 +43,7 @@ func (h *profileLoaderById) Execute(testName string) error { type customProfileLoader struct{} func (h *customProfileLoader) Execute(filepath string) error { - results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", filepath) + results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", filepath) if err != nil { return errorutil.NewWithErr(err).Msgf("failed to load template with id") } diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 2fe3694e6..a44568af2 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -13,14 +13,15 @@ import ( "strings" "time" + "github.com/projectdiscovery/gologger" _pdcp "github.com/projectdiscovery/nuclei/v3/internal/pdcp" "github.com/projectdiscovery/utils/auth/pdcp" "github.com/projectdiscovery/utils/env" _ "github.com/projectdiscovery/utils/pprof" stringsutil "github.com/projectdiscovery/utils/strings" + "github.com/rs/xid" "github.com/projectdiscovery/goflags" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/gologger/levels" "github.com/projectdiscovery/interactsh/pkg/client" "github.com/projectdiscovery/nuclei/v3/internal/runner" @@ -52,16 +53,18 @@ var ( ) func main() { + options.Logger = gologger.DefaultLogger + // enables CLI specific configs mostly interactive behavior config.CurrentAppMode = config.AppModeCLI if err := runner.ConfigureOptions(); err != nil { - gologger.Fatal().Msgf("Could not initialize options: %s\n", err) + options.Logger.Fatal().Msgf("Could not initialize options: %s\n", err) } _ = readConfig() if options.ListDslSignatures { - gologger.Info().Msgf("The available custom DSL functions are:") + options.Logger.Info().Msgf("The available custom DSL functions are:") fmt.Println(dsl.GetPrintableDslFunctionSignatures(options.NoColor)) return } @@ -72,7 +75,7 @@ func main() { templates.UseOptionsForSigner(options) tsigner, err := signer.NewTemplateSigner(nil, nil) // will read from env , config or generate new keys if err != nil { - gologger.Fatal().Msgf("couldn't initialize signer crypto engine: %s\n", err) + options.Logger.Fatal().Msgf("couldn't initialize signer crypto engine: %s\n", err) } successCounter := 0 @@ -88,7 +91,7 @@ func main() { if err != templates.ErrNotATemplate { // skip warnings and errors as given items are not templates errorCounter++ - gologger.Error().Msgf("could not sign '%s': %s\n", iterItem, err) + options.Logger.Error().Msgf("could not sign '%s': %s\n", iterItem, err) } } else { successCounter++ @@ -97,10 +100,10 @@ func main() { return nil }) if err != nil { - gologger.Error().Msgf("%s\n", err) + options.Logger.Error().Msgf("%s\n", err) } } - gologger.Info().Msgf("All templates signatures were elaborated success=%d failed=%d\n", successCounter, errorCounter) + options.Logger.Info().Msgf("All templates signatures were elaborated success=%d failed=%d\n", successCounter, errorCounter) return } @@ -111,7 +114,7 @@ func main() { createProfileFile := func(ext, profileType string) *os.File { f, err := os.Create(memProfile + ext) if err != nil { - gologger.Fatal().Msgf("profile: could not create %s profile %q file: %v", profileType, f.Name(), err) + options.Logger.Fatal().Msgf("profile: could not create %s profile %q file: %v", profileType, f.Name(), err) } return f } @@ -125,18 +128,18 @@ func main() { // Start tracing if err := trace.Start(traceFile); err != nil { - gologger.Fatal().Msgf("profile: could not start trace: %v", err) + options.Logger.Fatal().Msgf("profile: could not start trace: %v", err) } // Start CPU profiling if err := pprof.StartCPUProfile(cpuProfileFile); err != nil { - gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err) + options.Logger.Fatal().Msgf("profile: could not start CPU profile: %v", err) } defer func() { // Start heap memory snapshot if err := pprof.WriteHeapProfile(memProfileFile); err != nil { - gologger.Fatal().Msgf("profile: could not write memory profile: %v", err) + options.Logger.Fatal().Msgf("profile: could not write memory profile: %v", err) } pprof.StopCPUProfile() @@ -146,24 +149,26 @@ func main() { runtime.MemProfileRate = oldMemProfileRate - gologger.Info().Msgf("CPU profile saved at %q", cpuProfileFile.Name()) - gologger.Info().Msgf("Memory usage snapshot saved at %q", memProfileFile.Name()) - gologger.Info().Msgf("Traced at %q", traceFile.Name()) + options.Logger.Info().Msgf("CPU profile saved at %q", cpuProfileFile.Name()) + options.Logger.Info().Msgf("Memory usage snapshot saved at %q", memProfileFile.Name()) + options.Logger.Info().Msgf("Traced at %q", traceFile.Name()) }() } + options.ExecutionId = xid.New().String() + runner.ParseOptions(options) if options.ScanUploadFile != "" { if err := runner.UploadResultsToCloud(options); err != nil { - gologger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err) + options.Logger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err) } return } nucleiRunner, err := runner.New(options) if err != nil { - gologger.Fatal().Msgf("Could not create runner: %s\n", err) + options.Logger.Fatal().Msgf("Could not create runner: %s\n", err) } if nucleiRunner == nil { return @@ -176,10 +181,10 @@ func main() { stackMonitor.RegisterCallback(func(dumpID string) error { resumeFileName := fmt.Sprintf("crash-resume-file-%s.dump", dumpID) if options.EnableCloudUpload { - gologger.Info().Msgf("Uploading scan results to cloud...") + options.Logger.Info().Msgf("Uploading scan results to cloud...") } nucleiRunner.Close() - gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName) + options.Logger.Info().Msgf("Creating resume file: %s\n", resumeFileName) err := nucleiRunner.SaveResumeConfig(resumeFileName) if err != nil { return errorutil.NewWithErr(err).Msgf("couldn't create crash resume file") @@ -191,37 +196,35 @@ func main() { // Setup graceful exits resumeFileName := types.DefaultResumeFilePath() c := make(chan os.Signal, 1) - defer close(c) signal.Notify(c, os.Interrupt) go func() { - for range c { - gologger.Info().Msgf("CTRL+C pressed: Exiting\n") - if options.DASTServer { - nucleiRunner.Close() - os.Exit(1) - } - - gologger.Info().Msgf("Attempting graceful shutdown...") - if options.EnableCloudUpload { - gologger.Info().Msgf("Uploading scan results to cloud...") - } + <-c + options.Logger.Info().Msgf("CTRL+C pressed: Exiting\n") + if options.DASTServer { nucleiRunner.Close() - if options.ShouldSaveResume() { - gologger.Info().Msgf("Creating resume file: %s\n", resumeFileName) - err := nucleiRunner.SaveResumeConfig(resumeFileName) - if err != nil { - gologger.Error().Msgf("Couldn't create resume file: %s\n", err) - } - } os.Exit(1) } + + options.Logger.Info().Msgf("Attempting graceful shutdown...") + if options.EnableCloudUpload { + options.Logger.Info().Msgf("Uploading scan results to cloud...") + } + nucleiRunner.Close() + if options.ShouldSaveResume() { + options.Logger.Info().Msgf("Creating resume file: %s\n", resumeFileName) + err := nucleiRunner.SaveResumeConfig(resumeFileName) + if err != nil { + options.Logger.Error().Msgf("Couldn't create resume file: %s\n", err) + } + } + os.Exit(1) }() if err := nucleiRunner.RunEnumeration(); err != nil { if options.Validate { - gologger.Fatal().Msgf("Could not validate templates: %s\n", err) + options.Logger.Fatal().Msgf("Could not validate templates: %s\n", err) } else { - gologger.Fatal().Msgf("Could not run nuclei: %s\n", err) + options.Logger.Fatal().Msgf("Could not run nuclei: %s\n", err) } } nucleiRunner.Close() @@ -542,11 +545,11 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started h := &pdcp.PDCPCredHandler{} _, err := h.GetCreds() if err != nil { - gologger.Fatal().Msg("To utilize the `-ai` flag, please configure your API key with the `-auth` flag or set the `PDCP_API_KEY` environment variable") + options.Logger.Fatal().Msg("To utilize the `-ai` flag, please configure your API key with the `-auth` flag or set the `PDCP_API_KEY` environment variable") } } - gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug) + options.Logger.SetTimestamp(options.Timestamp, levels.LevelDebug) if options.VerboseVerbose { // hide release notes if silent mode is enabled @@ -570,11 +573,11 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started } if cfgFile != "" { if !fileutil.FileExists(cfgFile) { - gologger.Fatal().Msgf("given config file '%s' does not exist", cfgFile) + options.Logger.Fatal().Msgf("given config file '%s' does not exist", cfgFile) } // merge config file with flags if err := flagSet.MergeConfigFile(cfgFile); err != nil { - gologger.Fatal().Msgf("Could not read config: %s\n", err) + options.Logger.Fatal().Msgf("Could not read config: %s\n", err) } } if options.NewTemplatesDirectory != "" { @@ -587,7 +590,7 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started if tp := findProfilePathById(templateProfile, defaultProfilesPath); tp != "" { templateProfile = tp } else { - gologger.Fatal().Msgf("'%s' is not a profile-id or profile path", templateProfile) + options.Logger.Fatal().Msgf("'%s' is not a profile-id or profile path", templateProfile) } } if !filepath.IsAbs(templateProfile) { @@ -602,17 +605,17 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started } } if !fileutil.FileExists(templateProfile) { - gologger.Fatal().Msgf("given template profile file '%s' does not exist", templateProfile) + options.Logger.Fatal().Msgf("given template profile file '%s' does not exist", templateProfile) } if err := flagSet.MergeConfigFile(templateProfile); err != nil { - gologger.Fatal().Msgf("Could not read template profile: %s\n", err) + options.Logger.Fatal().Msgf("Could not read template profile: %s\n", err) } } if len(options.SecretsFile) > 0 { for _, secretFile := range options.SecretsFile { if !fileutil.FileExists(secretFile) { - gologger.Fatal().Msgf("given secrets file '%s' does not exist", options.SecretsFile) + options.Logger.Fatal().Msgf("given secrets file '%s' does not exist", secretFile) } } } @@ -638,25 +641,25 @@ func readFlagsConfig(flagset *goflags.FlagSet) { if err != nil { // something went wrong either dir is not readable or something else went wrong upstream in `goflags` // warn and exit in this case - gologger.Warning().Msgf("Could not read config file: %s\n", err) + options.Logger.Warning().Msgf("Could not read config file: %s\n", err) return } cfgFile := config.DefaultConfig.GetFlagsConfigFilePath() if !fileutil.FileExists(cfgFile) { if !fileutil.FileExists(defaultCfgFile) { // if default config does not exist, warn and exit - gologger.Warning().Msgf("missing default config file : %s", defaultCfgFile) + options.Logger.Warning().Msgf("missing default config file : %s", defaultCfgFile) return } // if does not exist copy it from the default config if err = fileutil.CopyFile(defaultCfgFile, cfgFile); err != nil { - gologger.Warning().Msgf("Could not copy config file: %s\n", err) + options.Logger.Warning().Msgf("Could not copy config file: %s\n", err) } return } // if config file exists, merge it with the default config if err = flagset.MergeConfigFile(cfgFile); err != nil { - gologger.Warning().Msgf("failed to merge configfile with flags got: %s\n", err) + options.Logger.Warning().Msgf("failed to merge configfile with flags got: %s\n", err) } } @@ -667,29 +670,29 @@ func disableUpdatesCallback() { // printVersion prints the nuclei version and exits. func printVersion() { - gologger.Info().Msgf("Nuclei Engine Version: %s", config.Version) - gologger.Info().Msgf("Nuclei Config Directory: %s", config.DefaultConfig.GetConfigDir()) - gologger.Info().Msgf("Nuclei Cache Directory: %s", config.DefaultConfig.GetCacheDir()) // cache dir contains resume files - gologger.Info().Msgf("PDCP Directory: %s", pdcp.PDCPDir) + options.Logger.Info().Msgf("Nuclei Engine Version: %s", config.Version) + options.Logger.Info().Msgf("Nuclei Config Directory: %s", config.DefaultConfig.GetConfigDir()) + options.Logger.Info().Msgf("Nuclei Cache Directory: %s", config.DefaultConfig.GetCacheDir()) // cache dir contains resume files + options.Logger.Info().Msgf("PDCP Directory: %s", pdcp.PDCPDir) os.Exit(0) } // printTemplateVersion prints the nuclei template version and exits. func printTemplateVersion() { cfg := config.DefaultConfig - gologger.Info().Msgf("Public nuclei-templates version: %s (%s)\n", cfg.TemplateVersion, cfg.TemplatesDirectory) + options.Logger.Info().Msgf("Public nuclei-templates version: %s (%s)\n", cfg.TemplateVersion, cfg.TemplatesDirectory) if fileutil.FolderExists(cfg.CustomS3TemplatesDirectory) { - gologger.Info().Msgf("Custom S3 templates location: %s\n", cfg.CustomS3TemplatesDirectory) + options.Logger.Info().Msgf("Custom S3 templates location: %s\n", cfg.CustomS3TemplatesDirectory) } if fileutil.FolderExists(cfg.CustomGitHubTemplatesDirectory) { - gologger.Info().Msgf("Custom GitHub templates location: %s ", cfg.CustomGitHubTemplatesDirectory) + options.Logger.Info().Msgf("Custom GitHub templates location: %s ", cfg.CustomGitHubTemplatesDirectory) } if fileutil.FolderExists(cfg.CustomGitLabTemplatesDirectory) { - gologger.Info().Msgf("Custom GitLab templates location: %s ", cfg.CustomGitLabTemplatesDirectory) + options.Logger.Info().Msgf("Custom GitLab templates location: %s ", cfg.CustomGitLabTemplatesDirectory) } if fileutil.FolderExists(cfg.CustomAzureTemplatesDirectory) { - gologger.Info().Msgf("Custom Azure templates location: %s ", cfg.CustomAzureTemplatesDirectory) + options.Logger.Info().Msgf("Custom Azure templates location: %s ", cfg.CustomAzureTemplatesDirectory) } os.Exit(0) } @@ -705,13 +708,13 @@ Following files will be deleted: Note: Make sure you have backup of your custom nuclei-templates before proceeding `, config.DefaultConfig.GetConfigDir(), config.DefaultConfig.TemplatesDirectory) - gologger.Print().Msg(warning) + options.Logger.Print().Msg(warning) reader := bufio.NewReader(os.Stdin) for { fmt.Print("Are you sure you want to continue? [y/n]: ") resp, err := reader.ReadString('\n') if err != nil { - gologger.Fatal().Msgf("could not read response: %s", err) + options.Logger.Fatal().Msgf("could not read response: %s", err) } resp = strings.TrimSpace(resp) if stringsutil.EqualFoldAny(resp, "y", "yes") { @@ -724,13 +727,13 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin } err := os.RemoveAll(config.DefaultConfig.GetConfigDir()) if err != nil { - gologger.Fatal().Msgf("could not delete config dir: %s", err) + options.Logger.Fatal().Msgf("could not delete config dir: %s", err) } err = os.RemoveAll(config.DefaultConfig.TemplatesDirectory) if err != nil { - gologger.Fatal().Msgf("could not delete templates dir: %s", err) + options.Logger.Fatal().Msgf("could not delete templates dir: %s", err) } - gologger.Info().Msgf("Successfully deleted all nuclei configurations files and nuclei-templates") + options.Logger.Info().Msgf("Successfully deleted all nuclei configurations files and nuclei-templates") os.Exit(0) } @@ -750,7 +753,7 @@ func findProfilePathById(profileId, templatesDir string) string { return nil }) if err != nil && err.Error() != "FOUND" { - gologger.Error().Msgf("%s\n", err) + options.Logger.Error().Msgf("%s\n", err) } return profilePath } diff --git a/cmd/nuclei/main_benchmark_test.go b/cmd/nuclei/main_benchmark_test.go index f8504f8cc..04e17bf90 100644 --- a/cmd/nuclei/main_benchmark_test.go +++ b/cmd/nuclei/main_benchmark_test.go @@ -20,7 +20,6 @@ var ( func TestMain(m *testing.M) { // Set up - gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) _ = os.Setenv("DISABLE_STDOUT", "true") @@ -93,6 +92,8 @@ func getDefaultOptions() *types.Options { LoadHelperFileFunction: types.DefaultOptions().LoadHelperFileFunction, // DialerKeepAlive: time.Duration(0), // DASTServerAddress: "localhost:9055", + ExecutionId: "test", + Logger: gologger.DefaultLogger, } } diff --git a/cmd/tmc/main.go b/cmd/tmc/main.go index aad80dd32..8e4eb1ed2 100644 --- a/cmd/tmc/main.go +++ b/cmd/tmc/main.go @@ -146,8 +146,8 @@ func process(opts options) error { gologger.Fatal().Msgf("could not open error log file: %s\n", err) } defer func() { - _ = errFile.Close() - }() + _ = errFile.Close() + }() } templateCatalog := disk.NewCatalog(filepath.Dir(opts.input)) @@ -401,7 +401,7 @@ func parseAndAddMaxRequests(catalog catalog.Catalog, path, data string) (string, // parseTemplate parses a template and returns the template object func parseTemplate(catalog catalog.Catalog, templatePath string) (*templates.Template, error) { - executorOpts := protocols.ExecutorOptions{ + executorOpts := &protocols.ExecutorOptions{ Catalog: catalog, Options: defaultOpts, } diff --git a/cmd/tools/signer/main.go b/cmd/tools/signer/main.go index 290572efb..6f53b50c8 100644 --- a/cmd/tools/signer/main.go +++ b/cmd/tools/signer/main.go @@ -99,12 +99,12 @@ func main() { gologger.Info().Msgf("✓ Template signed & verified successfully") } -func defaultExecutorOpts(templatePath string) protocols.ExecutorOptions { +func defaultExecutorOpts(templatePath string) *protocols.ExecutorOptions { // use parsed options when initializing signer instead of default options options := types.DefaultOptions() templates.UseOptionsForSigner(options) catalog := disk.NewCatalog(filepath.Dir(templatePath)) - executerOpts := protocols.ExecutorOptions{ + executerOpts := &protocols.ExecutorOptions{ Catalog: catalog, Options: options, TemplatePath: templatePath, diff --git a/go.mod b/go.mod index 2d3cb8e10..99539206c 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,8 @@ require ( github.com/DataDog/gostackparse v0.7.0 github.com/Masterminds/semver/v3 v3.4.0 github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 - github.com/alecthomas/chroma v0.10.0 + github.com/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697 + github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883 github.com/alitto/pond v1.9.2 github.com/antchfx/xmlquery v1.4.4 github.com/antchfx/xpath v1.3.4 @@ -66,11 +67,8 @@ require ( github.com/clbanning/mxj/v2 v2.7.0 github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c github.com/docker/go-units v0.5.0 - github.com/dop251/goja v0.0.0-20250624190929-4d26883d182a - github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 github.com/fatih/structs v1.1.0 github.com/getkin/kin-openapi v0.132.0 - github.com/go-echarts/go-echarts/v2 v2.6.0 github.com/go-git/go-git/v5 v5.16.2 github.com/go-ldap/ldap/v3 v3.4.11 github.com/go-pg/pg v8.0.7+incompatible @@ -114,14 +112,11 @@ require ( github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 github.com/stretchr/testify v1.10.0 github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 - github.com/trivago/tgo v1.0.7 github.com/yassinebenaid/godump v0.11.1 github.com/zmap/zgrab2 v0.1.8 gitlab.com/gitlab-org/api/client-go v0.130.1 go.mongodb.org/mongo-driver v1.17.4 - golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b golang.org/x/term v0.32.0 - golang.org/x/tools v0.34.0 gopkg.in/yaml.v3 v3.0.1 moul.io/http2curl v1.0.0 ) @@ -194,7 +189,6 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect github.com/docker/cli v27.4.1+incompatible // indirect github.com/docker/docker v27.1.1+incompatible // indirect @@ -219,12 +213,8 @@ 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/goburrow/cache v0.1.4 // indirect - github.com/gobwas/httphead v0.1.0 // indirect - github.com/gobwas/pool v0.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect @@ -232,20 +222,19 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.1.4 // indirect github.com/google/go-github/v30 v30.1.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect github.com/hdm/jarm-go v0.0.7 // indirect - github.com/imdario/mergo v0.3.13 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect @@ -310,8 +299,6 @@ require ( 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.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // 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 @@ -345,33 +332,52 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/ysmood/fetchup v0.2.3 // indirect - github.com/ysmood/goob v0.4.0 // indirect github.com/ysmood/got v0.40.0 // indirect - github.com/ysmood/gson v0.7.3 // indirect - github.com/ysmood/leakless v0.9.0 // indirect github.com/yuin/goldmark v1.7.8 // indirect github.com/yuin/goldmark-emoji v1.0.5 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zcalusic/sysinfo v1.0.2 // indirect github.com/zeebo/blake3 v0.2.3 // indirect + go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/sync v0.15.0 // indirect + gopkg.in/djherbis/times.v1 v1.3.0 // indirect + mellium.im/sasl v0.3.2 // indirect +) + +require ( + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/goburrow/cache v0.1.4 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect + github.com/trivago/tgo v1.0.7 + github.com/ysmood/goob v0.4.0 // indirect + github.com/ysmood/gson v0.7.3 // indirect + github.com/ysmood/leakless v0.9.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // indirect go.etcd.io/bbolt v1.3.10 // indirect go.uber.org/zap v1.25.0 // indirect - go4.org v0.0.0-20230225012048-214862532bf5 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.39.0 // indirect + golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b golang.org/x/mod v0.25.0 // indirect - golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/time v0.11.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + golang.org/x/tools v0.34.0 + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect - gopkg.in/djherbis/times.v1 v1.3.0 // indirect +) + +require ( + github.com/alecthomas/chroma v0.10.0 + github.com/go-echarts/go-echarts/v2 v2.6.0 gopkg.in/warnings.v0 v0.1.2 // indirect - mellium.im/sasl v0.3.2 // indirect ) // https://go.dev/ref/mod#go-mod-file-retract diff --git a/go.sum b/go.sum index 11c9848e2..13329fc0e 100644 --- a/go.sum +++ b/go.sum @@ -83,6 +83,10 @@ github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 h1:KFac3SiGbId8ub github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057/go.mod h1:iLB2pivrPICvLOuROKmlqURtFIEsoJZaMidQfCG1+D4= github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 h1:ZbFL+BDfBqegi+/Ssh7im5+aQfBRx6it+kHnC7jaDU8= github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809/go.mod h1:upgc3Zs45jBDnBT4tVRgRcgm26ABpaP7MoTSdgysca4= +github.com/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697 h1:54I+OF5vS4a/rxnUrN5J3hi0VEYKcrTlpc8JosDyP+c= +github.com/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697/go.mod h1:yNqYRqxYkSROY1J+LX+A0tOSA/6soXQs5m8hZSqYBac= +github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883 h1:+Is1AS20q3naP+qJophNpxuvx1daFOx9C0kLIuI0GVk= +github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883/go.mod h1:K+FhM7iKGKtalkeXGEviafPPwyVjDv1a/ehomabLF2w= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -299,10 +303,6 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj 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= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dop251/goja v0.0.0-20250624190929-4d26883d182a h1:QIWJoaD2+zxUjN28l8zixmbuvtYqqcxj49Iwzw7mDpk= -github.com/dop251/goja v0.0.0-20250624190929-4d26883d182a/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= -github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 h1:fuHXpEVTTk7TilRdfGRLHpiTD6tnT0ihEowCfWjlFvw= -github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0/go.mod h1:Tb7Xxye4LX7cT3i8YLvmPMGCV92IOi4CDZvm/V8ylc0= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= @@ -315,8 +315,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -399,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= @@ -524,8 +522,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -545,8 +543,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= @@ -654,7 +652,6 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -720,8 +717,6 @@ github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5 github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ= github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1470,8 +1465,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1499,7 +1494,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= diff --git a/internal/pdcp/writer.go b/internal/pdcp/writer.go index fb3c058d1..19e2c7e84 100644 --- a/internal/pdcp/writer.go +++ b/internal/pdcp/writer.go @@ -55,10 +55,11 @@ type UploadWriter struct { scanName string counter atomic.Int32 TeamID string + Logger *gologger.Logger } // NewUploadWriter creates a new upload writer -func NewUploadWriter(ctx context.Context, creds *pdcpauth.PDCPCredentials) (*UploadWriter, error) { +func NewUploadWriter(ctx context.Context, logger *gologger.Logger, creds *pdcpauth.PDCPCredentials) (*UploadWriter, error) { if creds == nil { return nil, fmt.Errorf("no credentials provided") } @@ -66,6 +67,7 @@ func NewUploadWriter(ctx context.Context, creds *pdcpauth.PDCPCredentials) (*Upl creds: creds, done: make(chan struct{}, 1), TeamID: NoneTeamID, + Logger: logger, } var err error reader, writer := io.Pipe() @@ -128,8 +130,8 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { // continuously read from the reader and send to channel go func() { defer func() { - _ = r.Close() - }() + _ = r.Close() + }() defer close(ch) for { data, err := reader.ReadString('\n') @@ -147,9 +149,9 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { close(u.done) // if no scanid is generated no results were uploaded if u.scanID == "" { - gologger.Verbose().Msgf("Scan results upload to cloud skipped, no results found to upload") + u.Logger.Verbose().Msgf("Scan results upload to cloud skipped, no results found to upload") } else { - gologger.Info().Msgf("%v Scan results uploaded to cloud, you can view scan results at %v", u.counter.Load(), getScanDashBoardURL(u.scanID, u.TeamID)) + u.Logger.Info().Msgf("%v Scan results uploaded to cloud, you can view scan results at %v", u.counter.Load(), getScanDashBoardURL(u.scanID, u.TeamID)) } }() // temporary buffer to store the results @@ -162,7 +164,7 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { // flush before exit if buff.Len() > 0 { if err := u.uploadChunk(buff); err != nil { - gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err) + u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err) } } return @@ -170,14 +172,14 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { // flush the buffer if buff.Len() > 0 { if err := u.uploadChunk(buff); err != nil { - gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err) + u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err) } } case line, ok := <-ch: if !ok { if buff.Len() > 0 { if err := u.uploadChunk(buff); err != nil { - gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err) + u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err) } } return @@ -185,7 +187,7 @@ func (u *UploadWriter) autoCommit(ctx context.Context, r *io.PipeReader) { if buff.Len()+len(line) > MaxChunkSize { // flush existing buffer if err := u.uploadChunk(buff); err != nil { - gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err) + u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err) } } else { buff.WriteString(line) @@ -202,7 +204,7 @@ func (u *UploadWriter) uploadChunk(buff *bytes.Buffer) error { // if successful, reset the buffer buff.Reset() // log in verbose mode - gologger.Warning().Msgf("Uploaded results chunk, you can view scan results at %v", getScanDashBoardURL(u.scanID, u.TeamID)) + u.Logger.Warning().Msgf("Uploaded results chunk, you can view scan results at %v", getScanDashBoardURL(u.scanID, u.TeamID)) return nil } @@ -216,8 +218,8 @@ func (u *UploadWriter) upload(data []byte) error { return errorutil.NewWithErr(err).Msgf("could not upload results") } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() bin, err := io.ReadAll(resp.Body) if err != nil { return errorutil.NewWithErr(err).Msgf("could not get id from response") @@ -260,7 +262,7 @@ func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) { if u.scanName != "" && req.Path == uploadEndpoint { req.Params.Add("name", u.scanName) } - req.URL.Update() + req.Update() req.Header.Set(pdcpauth.ApiKeyHeaderName, u.creds.APIKey) if u.TeamID != NoneTeamID && u.TeamID != "" { diff --git a/internal/runner/inputs.go b/internal/runner/inputs.go index 3d51ca7e8..cb782f736 100644 --- a/internal/runner/inputs.go +++ b/internal/runner/inputs.go @@ -2,11 +2,11 @@ package runner import ( "context" + "fmt" "sync/atomic" "time" "github.com/pkg/errors" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/hmap/store/hybrid" "github.com/projectdiscovery/httpx/common/httpx" "github.com/projectdiscovery/nuclei/v3/pkg/input/provider" @@ -28,7 +28,7 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { // currently http probing for input mode types is not supported return hm, nil } - gologger.Info().Msgf("Running httpx on input host") + r.Logger.Info().Msgf("Running httpx on input host") httpxOptions := httpx.DefaultOptions if r.options.AliveHttpProxy != "" { @@ -38,7 +38,13 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { } httpxOptions.RetryMax = r.options.Retries httpxOptions.Timeout = time.Duration(r.options.Timeout) * time.Second - httpxOptions.NetworkPolicy = protocolstate.NetworkPolicy + + dialers := protocolstate.GetDialersWithId(r.options.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", r.options.ExecutionId) + } + + httpxOptions.NetworkPolicy = dialers.NetworkPolicy httpxClient, err := httpx.New(&httpxOptions) if err != nil { return nil, errors.Wrap(err, "could not create httpx client") @@ -57,7 +63,7 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { if r.options.ProbeConcurrency > 0 && swg.Size != r.options.ProbeConcurrency { if err := swg.Resize(context.Background(), r.options.ProbeConcurrency); err != nil { - gologger.Error().Msgf("Could not resize workpool: %s\n", err) + r.Logger.Error().Msgf("Could not resize workpool: %s\n", err) } } @@ -74,6 +80,6 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) { }) swg.Wait() - gologger.Info().Msgf("Found %d URL from httpx", count.Load()) + r.Logger.Info().Msgf("Found %d URL from httpx", count.Load()) return hm, nil } diff --git a/internal/runner/lazy.go b/internal/runner/lazy.go index 30cca8e1d..30664bfd5 100644 --- a/internal/runner/lazy.go +++ b/internal/runner/lazy.go @@ -22,12 +22,12 @@ import ( type AuthLazyFetchOptions struct { TemplateStore *loader.Store - ExecOpts protocols.ExecutorOptions + ExecOpts *protocols.ExecutorOptions OnError func(error) } // GetAuthTmplStore create new loader for loading auth templates -func GetAuthTmplStore(opts types.Options, catalog catalog.Catalog, execOpts protocols.ExecutorOptions) (*loader.Store, error) { +func GetAuthTmplStore(opts *types.Options, catalog catalog.Catalog, execOpts *protocols.ExecutorOptions) (*loader.Store, error) { tmpls := []string{} for _, file := range opts.SecretsFile { data, err := authx.GetTemplatePathsFromSecretFile(file) @@ -54,7 +54,7 @@ func GetAuthTmplStore(opts types.Options, catalog catalog.Catalog, execOpts prot opts.Protocols = nil opts.ExcludeProtocols = nil opts.IncludeConditions = nil - cfg := loader.NewConfig(&opts, catalog, execOpts) + cfg := loader.NewConfig(opts, catalog, execOpts) cfg.StoreId = loader.AuthStoreId store, err := loader.New(cfg) if err != nil { diff --git a/internal/runner/options.go b/internal/runner/options.go index 57b28973b..bd6b92bc0 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -31,7 +31,6 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/utils/yaml" fileutil "github.com/projectdiscovery/utils/file" "github.com/projectdiscovery/utils/generic" - logutil "github.com/projectdiscovery/utils/log" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -71,17 +70,17 @@ func ParseOptions(options *types.Options) { vardump.Limit = options.VarDumpLimit } if options.ShowActions { - gologger.Info().Msgf("Showing available headless actions: ") + options.Logger.Info().Msgf("Showing available headless actions: ") for action := range engine.ActionStringToAction { - gologger.Print().Msgf("\t%s", action) + options.Logger.Print().Msgf("\t%s", action) } os.Exit(0) } defaultProfilesPath := filepath.Join(config.DefaultConfig.GetTemplateDir(), "profiles") if options.ListTemplateProfiles { - gologger.Print().Msgf( - "\nListing available %v nuclei template profiles for %v", + options.Logger.Print().Msgf( + "Listing available %v nuclei template profiles for %v", config.DefaultConfig.TemplateVersion, config.DefaultConfig.TemplatesDirectory, ) @@ -93,23 +92,23 @@ func ParseOptions(options *types.Options) { return nil } if profileRelPath, err := filepath.Rel(templatesRootDir, iterItem); err == nil { - gologger.Print().Msgf("%s (%s)\n", profileRelPath, strings.TrimSuffix(filepath.Base(iterItem), ext)) + options.Logger.Print().Msgf("%s (%s)\n", profileRelPath, strings.TrimSuffix(filepath.Base(iterItem), ext)) } return nil }) if err != nil { - gologger.Error().Msgf("%s\n", err) + options.Logger.Error().Msgf("%s\n", err) } os.Exit(0) } if options.StoreResponseDir != DefaultDumpTrafficOutputFolder && !options.StoreResponse { - gologger.Debug().Msgf("Store response directory specified, enabling \"store-resp\" flag automatically\n") + options.Logger.Debug().Msgf("Store response directory specified, enabling \"store-resp\" flag automatically\n") options.StoreResponse = true } // Validate the options passed by the user and if any // invalid options have been used, exit. if err := ValidateOptions(options); err != nil { - gologger.Fatal().Msgf("Program exiting: %s\n", err) + options.Logger.Fatal().Msgf("Program exiting: %s\n", err) } // Load the resolvers if user asked for them @@ -117,7 +116,7 @@ func ParseOptions(options *types.Options) { err := protocolinit.Init(options) if err != nil { - gologger.Fatal().Msgf("Could not initialize protocols: %s\n", err) + options.Logger.Fatal().Msgf("Could not initialize protocols: %s\n", err) } // Set GitHub token in env variable. runner.getGHClientWithToken() reads token from env @@ -169,7 +168,7 @@ func ValidateOptions(options *types.Options) error { return err } if options.Validate { - validateTemplatePaths(config.DefaultConfig.TemplatesDirectory, options.Templates, options.Workflows) + validateTemplatePaths(options.Logger, config.DefaultConfig.TemplatesDirectory, options.Templates, options.Workflows) } if options.DAST { if err := validateDASTOptions(options); err != nil { @@ -182,7 +181,7 @@ func ValidateOptions(options *types.Options) error { if generic.EqualsAny("", options.ClientCertFile, options.ClientKeyFile, options.ClientCAFile) { return errors.New("if a client certification option is provided, then all three must be provided") } - validateCertificatePaths(options.ClientCertFile, options.ClientKeyFile, options.ClientCAFile) + validateCertificatePaths(options.Logger, options.ClientCertFile, options.ClientKeyFile, options.ClientCAFile) } // Verify AWS secrets are passed if a S3 template bucket is passed if options.AwsBucketName != "" && options.UpdateTemplates && !options.AwsTemplateDisableDownload { @@ -305,8 +304,8 @@ func createReportingOptions(options *types.Options) (*reporting.Options, error) return nil, errors.Wrap(err, "could not open reporting config file") } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() if err := yaml.DecodeAndValidate(file, reportingOptions); err != nil { return nil, errors.Wrap(err, "could not parse reporting config file") @@ -344,32 +343,33 @@ func createReportingOptions(options *types.Options) (*reporting.Options, error) } reportingOptions.OmitRaw = options.OmitRawRequests + reportingOptions.ExecutionId = options.ExecutionId return reportingOptions, nil } // configureOutput configures the output logging levels to be displayed on the screen func configureOutput(options *types.Options) { if options.NoColor { - gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true)) + options.Logger.SetFormatter(formatter.NewCLI(true)) } // If the user desires verbose output, show verbose output if options.Debug || options.DebugRequests || options.DebugResponse { - gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug) + options.Logger.SetMaxLevel(levels.LevelDebug) } // Debug takes precedence before verbose // because debug is a lower logging level. if options.Verbose || options.Validate { - gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose) + options.Logger.SetMaxLevel(levels.LevelVerbose) } if options.NoColor { - gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true)) + options.Logger.SetFormatter(formatter.NewCLI(true)) } if options.Silent { - gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) + options.Logger.SetMaxLevel(levels.LevelSilent) } // disable standard logger (ref: https://github.com/golang/go/issues/19895) - logutil.DisableDefaultLogger() + // logutil.DisableDefaultLogger() } // loadResolvers loads resolvers from both user-provided flags and file @@ -380,11 +380,11 @@ func loadResolvers(options *types.Options) { file, err := os.Open(options.ResolversFile) if err != nil { - gologger.Fatal().Msgf("Could not open resolvers file: %s\n", err) + options.Logger.Fatal().Msgf("Could not open resolvers file: %s\n", err) } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() scanner := bufio.NewScanner(file) for scanner.Scan() { @@ -400,7 +400,7 @@ func loadResolvers(options *types.Options) { } } -func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPaths []string) { +func validateTemplatePaths(logger *gologger.Logger, templatesDirectory string, templatePaths, workflowPaths []string) { allGivenTemplatePaths := append(templatePaths, workflowPaths...) for _, templatePath := range allGivenTemplatePaths { if templatesDirectory != templatePath && filepath.IsAbs(templatePath) { @@ -408,7 +408,7 @@ func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPat if err == nil && fileInfo.IsDir() { relativizedPath, err2 := filepath.Rel(templatesDirectory, templatePath) if err2 != nil || (len(relativizedPath) >= 2 && relativizedPath[:2] == "..") { - gologger.Warning().Msgf("The given path (%s) is outside the default template directory path (%s)! "+ + logger.Warning().Msgf("The given path (%s) is outside the default template directory path (%s)! "+ "Referenced sub-templates with relative paths in workflows will be resolved against the default template directory.", templatePath, templatesDirectory) break } @@ -417,12 +417,12 @@ func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPat } } -func validateCertificatePaths(certificatePaths ...string) { +func validateCertificatePaths(logger *gologger.Logger, certificatePaths ...string) { for _, certificatePath := range certificatePaths { if !fileutil.FileExists(certificatePath) { // The provided path to the PEM certificate does not exist for the client authentication. As this is // required for successful authentication, log and return an error - gologger.Fatal().Msgf("The given path (%s) to the certificate does not exist!", certificatePath) + logger.Fatal().Msgf("The given path (%s) to the certificate does not exist!", certificatePath) break } } @@ -449,7 +449,7 @@ func readEnvInputVars(options *types.Options) { // Attempt to convert the repo ID to an integer repoIDInt, err := strconv.Atoi(repoID) if err != nil { - gologger.Warning().Msgf("Invalid GitLab template repository ID: %s", repoID) + options.Logger.Warning().Msgf("Invalid GitLab template repository ID: %s", repoID) continue } diff --git a/internal/runner/proxy.go b/internal/runner/proxy.go index ca6a6dbba..ec14302eb 100644 --- a/internal/runner/proxy.go +++ b/internal/runner/proxy.go @@ -7,7 +7,6 @@ import ( "os" "strings" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" fileutil "github.com/projectdiscovery/utils/file" @@ -31,8 +30,8 @@ func loadProxyServers(options *types.Options) error { return fmt.Errorf("could not open proxy file: %w", err) } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() scanner := bufio.NewScanner(file) for scanner.Scan() { proxy := scanner.Text() @@ -58,11 +57,11 @@ func loadProxyServers(options *types.Options) error { } switch proxyURL.Scheme { case proxyutils.HTTP, proxyutils.HTTPS: - gologger.Verbose().Msgf("Using %s as proxy server", proxyURL.String()) + options.Logger.Verbose().Msgf("Using %s as proxy server", proxyURL.String()) options.AliveHttpProxy = proxyURL.String() case proxyutils.SOCKS5: options.AliveSocksProxy = proxyURL.String() - gologger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String()) + options.Logger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String()) } return nil } diff --git a/internal/runner/runner.go b/internal/runner/runner.go index b046443b0..b32f7e2f6 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -10,6 +10,7 @@ import ( "sync/atomic" "time" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/internal/pdcp" "github.com/projectdiscovery/nuclei/v3/internal/server" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider" @@ -32,7 +33,6 @@ import ( "github.com/pkg/errors" "github.com/projectdiscovery/ratelimit" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/internal/colorizer" "github.com/projectdiscovery/nuclei/v3/internal/httpapi" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" @@ -95,6 +95,7 @@ type Runner struct { inputProvider provider.InputProvider fuzzFrequencyCache *frequency.Tracker httpStats *outputstats.Tracker + Logger *gologger.Logger //general purpose temporary directory tmpDir string @@ -108,10 +109,11 @@ type Runner struct { func New(options *types.Options) (*Runner, error) { runner := &Runner{ options: options, + Logger: options.Logger, } if options.HealthCheck { - gologger.Print().Msgf("%s\n", DoHealthCheck(options)) + runner.Logger.Print().Msgf("%s\n", DoHealthCheck(options)) os.Exit(0) } @@ -119,14 +121,14 @@ func New(options *types.Options) (*Runner, error) { if config.DefaultConfig.CanCheckForUpdates() { if err := installer.NucleiVersionCheck(); err != nil { if options.Verbose || options.Debug { - gologger.Error().Msgf("nuclei version check failed got: %s\n", err) + runner.Logger.Error().Msgf("nuclei version check failed got: %s\n", err) } } // check for custom template updates and update if available ctm, err := customtemplates.NewCustomTemplatesManager(options) if err != nil { - gologger.Error().Label("custom-templates").Msgf("Failed to create custom templates manager: %s\n", err) + runner.Logger.Error().Label("custom-templates").Msgf("Failed to create custom templates manager: %s\n", err) } // Check for template updates and update if available. @@ -136,15 +138,15 @@ func New(options *types.Options) (*Runner, error) { DisablePublicTemplates: options.PublicTemplateDisableDownload, } if err := tm.FreshInstallIfNotExists(); err != nil { - gologger.Warning().Msgf("failed to install nuclei templates: %s\n", err) + runner.Logger.Warning().Msgf("failed to install nuclei templates: %s\n", err) } if err := tm.UpdateIfOutdated(); err != nil { - gologger.Warning().Msgf("failed to update nuclei templates: %s\n", err) + runner.Logger.Warning().Msgf("failed to update nuclei templates: %s\n", err) } if config.DefaultConfig.NeedsIgnoreFileUpdate() { if err := installer.UpdateIgnoreFile(); err != nil { - gologger.Warning().Msgf("failed to update nuclei ignore file: %s\n", err) + runner.Logger.Warning().Msgf("failed to update nuclei ignore file: %s\n", err) } } @@ -152,7 +154,7 @@ func New(options *types.Options) (*Runner, error) { // we automatically check for updates unless explicitly disabled // this print statement is only to inform the user that there are no updates if !config.DefaultConfig.NeedsTemplateUpdate() { - gologger.Info().Msgf("No new updates found for nuclei templates") + runner.Logger.Info().Msgf("No new updates found for nuclei templates") } // manually trigger update of custom templates if ctm != nil { @@ -161,20 +163,25 @@ func New(options *types.Options) (*Runner, error) { } } - parser := templates.NewParser() - - if options.Validate { - parser.ShouldValidate = true + if op, ok := options.Parser.(*templates.Parser); ok { + // Enable passing in an existing parser instance + // This uses a type assertion to avoid an import loop + runner.parser = op + } else { + parser := templates.NewParser() + if options.Validate { + parser.ShouldValidate = true + } + // TODO: refactor to pass options reference globally without cycles + parser.NoStrictSyntax = options.NoStrictSyntax + runner.parser = parser } - // TODO: refactor to pass options reference globally without cycles - parser.NoStrictSyntax = options.NoStrictSyntax - runner.parser = parser yaml.StrictSyntax = !options.NoStrictSyntax if options.Headless { if engine.MustDisableSandbox() { - gologger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n") + runner.Logger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n") } browser, err := engine.New(options) if err != nil { @@ -226,11 +233,11 @@ func New(options *types.Options) (*Runner, error) { if options.HttpApiEndpoint != "" { apiServer := httpapi.New(options.HttpApiEndpoint, options) - gologger.Info().Msgf("Listening api endpoint on: %s", options.HttpApiEndpoint) + runner.Logger.Info().Msgf("Listening api endpoint on: %s", options.HttpApiEndpoint) runner.httpApiEndpoint = apiServer go func() { if err := apiServer.Start(); err != nil { - gologger.Error().Msgf("Failed to start API server: %s", err) + runner.Logger.Error().Msgf("Failed to start API server: %s", err) } }() } @@ -284,7 +291,7 @@ func New(options *types.Options) (*Runner, error) { // create the resume configuration structure resumeCfg := types.NewResumeCfg() if runner.options.ShouldLoadResume() { - gologger.Info().Msg("Resuming from save checkpoint") + runner.Logger.Info().Msg("Resuming from save checkpoint") file, err := os.ReadFile(runner.options.Resume) if err != nil { return nil, err @@ -326,6 +333,7 @@ func New(options *types.Options) (*Runner, error) { } opts := interactsh.DefaultOptions(runner.output, runner.issuesClient, runner.progress) + opts.Logger = runner.Logger opts.Debug = runner.options.Debug opts.NoColor = runner.options.NoColor if options.InteractshURL != "" { @@ -355,13 +363,13 @@ func New(options *types.Options) (*Runner, error) { } interactshClient, err := interactsh.New(opts) if err != nil { - gologger.Error().Msgf("Could not create interactsh client: %s", err) + runner.Logger.Error().Msgf("Could not create interactsh client: %s", err) } else { runner.interactsh = interactshClient } if options.RateLimitMinute > 0 { - gologger.Print().Msgf("[%v] %v", aurora.BrightYellow("WRN"), "rate limit per minute is deprecated - use rate-limit-duration") + runner.Logger.Print().Msgf("[%v] %v", aurora.BrightYellow("WRN"), "rate limit per minute is deprecated - use rate-limit-duration") options.RateLimit = options.RateLimitMinute options.RateLimitDuration = time.Minute } @@ -382,7 +390,7 @@ func New(options *types.Options) (*Runner, error) { } // runStandardEnumeration runs standard enumeration -func (r *Runner) runStandardEnumeration(executerOpts protocols.ExecutorOptions, store *loader.Store, engine *core.Engine) (*atomic.Bool, error) { +func (r *Runner) runStandardEnumeration(executerOpts *protocols.ExecutorOptions, store *loader.Store, engine *core.Engine) (*atomic.Bool, error) { if r.options.AutomaticScan { return r.executeSmartWorkflowInput(executerOpts, store, engine) } @@ -413,7 +421,7 @@ func (r *Runner) Close() { if r.inputProvider != nil { r.inputProvider.Close() } - protocolinit.Close() + protocolinit.Close(r.options.ExecutionId) if r.pprofServer != nil { r.pprofServer.Stop() } @@ -440,22 +448,21 @@ func (r *Runner) setupPDCPUpload(writer output.Writer) output.Writer { r.options.EnableCloudUpload = true } if !r.options.EnableCloudUpload && !EnableCloudUpload { - r.pdcpUploadErrMsg = fmt.Sprintf("[%v] Scan results upload to cloud is disabled.", r.colorizer.BrightYellow("WRN")) + r.pdcpUploadErrMsg = "Scan results upload to cloud is disabled." return writer } - color := aurora.NewAurora(!r.options.NoColor) h := &pdcpauth.PDCPCredHandler{} creds, err := h.GetCreds() if err != nil { if err != pdcpauth.ErrNoCreds && !HideAutoSaveMsg { - gologger.Verbose().Msgf("Could not get credentials for cloud upload: %s\n", err) + r.Logger.Verbose().Msgf("Could not get credentials for cloud upload: %s\n", err) } - r.pdcpUploadErrMsg = fmt.Sprintf("[%v] To view results on Cloud Dashboard, Configure API key from %v", color.BrightYellow("WRN"), pdcpauth.DashBoardURL) + r.pdcpUploadErrMsg = fmt.Sprintf("To view results on Cloud Dashboard, configure API key from %v", pdcpauth.DashBoardURL) return writer } - uploadWriter, err := pdcp.NewUploadWriter(context.Background(), creds) + uploadWriter, err := pdcp.NewUploadWriter(context.Background(), r.Logger, creds) if err != nil { - r.pdcpUploadErrMsg = fmt.Sprintf("[%v] PDCP (%v) Auto-Save Failed: %s\n", color.BrightYellow("WRN"), pdcpauth.DashBoardURL, err) + r.pdcpUploadErrMsg = fmt.Sprintf("PDCP (%v) Auto-Save Failed: %s\n", pdcpauth.DashBoardURL, err) return writer } if r.options.ScanID != "" { @@ -491,6 +498,7 @@ func (r *Runner) RunEnumeration() error { Parser: r.parser, TemporaryDirectory: r.tmpDir, FuzzStatsDB: r.fuzzStats, + Logger: r.Logger, } dastServer, err := server.New(&server.Options{ Address: r.options.DASTServerAddress, @@ -532,7 +540,7 @@ func (r *Runner) RunEnumeration() error { // Create the executor options which will be used throughout the execution // stage by the nuclei engine modules. - executorOpts := protocols.ExecutorOptions{ + executorOpts := &protocols.ExecutorOptions{ Output: r.output, Options: r.options, Progress: r.progress, @@ -550,6 +558,8 @@ func (r *Runner) RunEnumeration() error { Parser: r.parser, FuzzParamsFrequency: fuzzFreqCache, GlobalMatchers: globalmatchers.New(), + DoNotCache: r.options.DoNotCacheTemplates, + Logger: r.Logger, } if config.DefaultConfig.IsDebugArgEnabled(config.DebugExportURLPattern) { @@ -558,7 +568,7 @@ func (r *Runner) RunEnumeration() error { } if len(r.options.SecretsFile) > 0 && !r.options.Validate { - authTmplStore, err := GetAuthTmplStore(*r.options, r.catalog, executorOpts) + authTmplStore, err := GetAuthTmplStore(r.options, r.catalog, executorOpts) if err != nil { return errors.Wrap(err, "failed to load dynamic auth templates") } @@ -578,8 +588,8 @@ func (r *Runner) RunEnumeration() error { if r.options.ShouldUseHostError() { maxHostError := r.options.MaxHostError if r.options.TemplateThreads > maxHostError { - gologger.Print().Msgf("[%v] The concurrency value is higher than max-host-error", r.colorizer.BrightYellow("WRN")) - gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", r.options.TemplateThreads) + r.Logger.Print().Msgf("[%v] The concurrency value is higher than max-host-error", r.colorizer.BrightYellow("WRN")) + r.Logger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", r.options.TemplateThreads) maxHostError = r.options.TemplateThreads } @@ -594,7 +604,7 @@ func (r *Runner) RunEnumeration() error { executorEngine := core.New(r.options) executorEngine.SetExecuterOptions(executorOpts) - workflowLoader, err := parsers.NewLoader(&executorOpts) + workflowLoader, err := parsers.NewLoader(executorOpts) if err != nil { return errors.Wrap(err, "Could not create loader.") } @@ -633,7 +643,7 @@ func (r *Runner) RunEnumeration() error { return err } if stats.GetValue(templates.SyntaxErrorStats) == 0 && stats.GetValue(templates.SyntaxWarningStats) == 0 && stats.GetValue(templates.RuntimeWarningsStats) == 0 { - gologger.Info().Msgf("All templates validated successfully\n") + r.Logger.Info().Msgf("All templates validated successfully") } else { return errors.New("encountered errors while performing template validation") } @@ -655,7 +665,7 @@ func (r *Runner) RunEnumeration() error { } ret := uncover.GetUncoverTargetsFromMetadata(context.TODO(), store.Templates(), r.options.UncoverField, uncoverOpts) for host := range ret { - _ = r.inputProvider.SetWithExclusions(host) + _ = r.inputProvider.SetWithExclusions(r.options.ExecutionId, host) } } // display execution info like version , templates used etc @@ -663,7 +673,7 @@ func (r *Runner) RunEnumeration() error { // prefetch secrets if enabled if executorOpts.AuthProvider != nil && r.options.PreFetchSecrets { - gologger.Info().Msgf("Pre-fetching secrets from authprovider[s]") + r.Logger.Info().Msgf("Pre-fetching secrets from authprovider[s]") if err := executorOpts.AuthProvider.PreFetchSecrets(); err != nil { return errors.Wrap(err, "could not pre-fetch secrets") } @@ -697,7 +707,7 @@ func (r *Runner) RunEnumeration() error { if r.dastServer != nil { go func() { if err := r.dastServer.Start(); err != nil { - gologger.Error().Msgf("could not start dast server: %v", err) + r.Logger.Error().Msgf("could not start dast server: %v", err) } }() } @@ -731,10 +741,10 @@ func (r *Runner) RunEnumeration() error { // todo: error propagation without canonical straight error check is required by cloud? // use safe dereferencing to avoid potential panics in case of previous unchecked errors if v := ptrutil.Safe(results); !v.Load() { - gologger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken)) + r.Logger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken)) } else { matchCount := r.output.ResultCount() - gologger.Info().Msgf("Scan completed in %s. %d matches found.", shortDur(timeTaken), matchCount) + r.Logger.Info().Msgf("Scan completed in %s. %d matches found.", shortDur(timeTaken), matchCount) } // check if a passive scan was requested but no target was provided @@ -775,7 +785,7 @@ func (r *Runner) isInputNonHTTP() bool { return nonURLInput } -func (r *Runner) executeSmartWorkflowInput(executorOpts protocols.ExecutorOptions, store *loader.Store, engine *core.Engine) (*atomic.Bool, error) { +func (r *Runner) executeSmartWorkflowInput(executorOpts *protocols.ExecutorOptions, store *loader.Store, engine *core.Engine) (*atomic.Bool, error) { r.progress.Init(r.inputProvider.Count(), 0, 0) service, err := automaticscan.New(automaticscan.Options{ @@ -843,7 +853,7 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) { if tmplCount == 0 && workflowCount == 0 { // if dast flag is used print explicit warning if r.options.DAST { - gologger.DefaultLogger.Print().Msgf("[%v] No DAST templates found", aurora.BrightYellow("WRN")) + r.Logger.Print().Msgf("[%v] No DAST templates found", aurora.BrightYellow("WRN")) } stats.ForceDisplayWarning(templates.SkippedCodeTmplTamperedStats) } else { @@ -867,34 +877,34 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) { gologger.Info().Msg(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates")) if !HideAutoSaveMsg { if r.pdcpUploadErrMsg != "" { - gologger.Print().Msgf("%s", r.pdcpUploadErrMsg) + r.Logger.Warning().Msgf("%s", r.pdcpUploadErrMsg) } else { - gologger.Info().Msgf("To view results on cloud dashboard, visit %v/scans upon scan completion.", pdcpauth.DashBoardURL) + r.Logger.Info().Msgf("To view results on cloud dashboard, visit %v/scans upon scan completion.", pdcpauth.DashBoardURL) } } if tmplCount > 0 || workflowCount > 0 { if len(store.Templates()) > 0 { - gologger.Info().Msgf("New templates added in latest release: %d", len(config.DefaultConfig.GetNewAdditions())) - gologger.Info().Msgf("Templates loaded for current scan: %d", len(store.Templates())) + r.Logger.Info().Msgf("New templates added in latest release: %d", len(config.DefaultConfig.GetNewAdditions())) + r.Logger.Info().Msgf("Templates loaded for current scan: %d", len(store.Templates())) } if len(store.Workflows()) > 0 { - gologger.Info().Msgf("Workflows loaded for current scan: %d", len(store.Workflows())) + r.Logger.Info().Msgf("Workflows loaded for current scan: %d", len(store.Workflows())) } for k, v := range templates.SignatureStats { value := v.Load() if value > 0 { if k == templates.Unsigned && !r.options.Silent && !config.DefaultConfig.HideTemplateSigWarning { - gologger.Print().Msgf("[%v] Loading %d unsigned templates for scan. Use with caution.", r.colorizer.BrightYellow("WRN"), value) + r.Logger.Print().Msgf("[%v] Loading %d unsigned templates for scan. Use with caution.", r.colorizer.BrightYellow("WRN"), value) } else { - gologger.Info().Msgf("Executing %d signed templates from %s", value, k) + r.Logger.Info().Msgf("Executing %d signed templates from %s", value, k) } } } } if r.inputProvider.Count() > 0 { - gologger.Info().Msgf("Targets loaded for current scan: %d", r.inputProvider.Count()) + r.Logger.Info().Msgf("Targets loaded for current scan: %d", r.inputProvider.Count()) } } @@ -921,7 +931,7 @@ func UploadResultsToCloud(options *types.Options) error { return errors.Wrap(err, "could not get credentials for cloud upload") } ctx := context.TODO() - uploadWriter, err := pdcp.NewUploadWriter(ctx, creds) + uploadWriter, err := pdcp.NewUploadWriter(ctx, options.Logger, creds) if err != nil { return errors.Wrap(err, "could not create upload writer") } @@ -941,20 +951,20 @@ func UploadResultsToCloud(options *types.Options) error { return errors.Wrap(err, "could not open scan upload file") } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() - gologger.Info().Msgf("Uploading scan results to cloud dashboard from %s", options.ScanUploadFile) + options.Logger.Info().Msgf("Uploading scan results to cloud dashboard from %s", options.ScanUploadFile) dec := json.NewDecoder(file) for dec.More() { var r output.ResultEvent err := dec.Decode(&r) if err != nil { - gologger.Warning().Msgf("Could not decode jsonl: %s\n", err) + options.Logger.Warning().Msgf("Could not decode jsonl: %s\n", err) continue } if err = uploadWriter.Write(&r); err != nil { - gologger.Warning().Msgf("[%s] failed to upload: %s\n", r.TemplateID, err) + options.Logger.Warning().Msgf("[%s] failed to upload: %s\n", r.TemplateID, err) } } uploadWriter.Close() diff --git a/internal/runner/templates.go b/internal/runner/templates.go index aaa08dd66..87182dcc3 100644 --- a/internal/runner/templates.go +++ b/internal/runner/templates.go @@ -12,7 +12,6 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/templates" "github.com/projectdiscovery/nuclei/v3/pkg/types" ) @@ -25,7 +24,7 @@ func (r *Runner) logAvailableTemplate(tplPath string) { panic("not a template") } if err != nil { - gologger.Error().Msgf("Could not parse file '%s': %s\n", tplPath, err) + r.Logger.Error().Msgf("Could not parse file '%s': %s\n", tplPath, err) } else { r.verboseTemplate(tpl) } @@ -33,14 +32,14 @@ func (r *Runner) logAvailableTemplate(tplPath string) { // log available templates for verbose (-vv) func (r *Runner) verboseTemplate(tpl *templates.Template) { - gologger.Print().Msgf("%s\n", templates.TemplateLogMessage(tpl.ID, + r.Logger.Print().Msgf("%s\n", templates.TemplateLogMessage(tpl.ID, types.ToString(tpl.Info.Name), tpl.Info.Authors.ToSlice(), tpl.Info.SeverityHolder.Severity)) } func (r *Runner) listAvailableStoreTemplates(store *loader.Store) { - gologger.Print().Msgf( + r.Logger.Print().Msgf( "\nListing available %v nuclei templates for %v", config.DefaultConfig.TemplateVersion, config.DefaultConfig.TemplatesDirectory, @@ -52,20 +51,20 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) { path := tpl.Path tplBody, err := store.ReadTemplateFromURI(path, true) if err != nil { - gologger.Error().Msgf("Could not read the template %s: %s", path, err) + r.Logger.Error().Msgf("Could not read the template %s: %s", path, err) continue } if colorize { path = aurora.Cyan(tpl.Path).String() tplBody, err = r.highlightTemplate(&tplBody) if err != nil { - gologger.Error().Msgf("Could not highlight the template %s: %s", tpl.Path, err) + r.Logger.Error().Msgf("Could not highlight the template %s: %s", tpl.Path, err) continue } } - gologger.Silent().Msgf("Template: %s\n\n%s", path, tplBody) + r.Logger.Print().Msgf("Template: %s\n\n%s", path, tplBody) } else { - gologger.Silent().Msgf("%s\n", strings.TrimPrefix(tpl.Path, config.DefaultConfig.TemplatesDirectory+string(filepath.Separator))) + r.Logger.Print().Msgf("%s\n", strings.TrimPrefix(tpl.Path, config.DefaultConfig.TemplatesDirectory+string(filepath.Separator))) } } else { r.verboseTemplate(tpl) @@ -74,7 +73,7 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) { } func (r *Runner) listAvailableStoreTags(store *loader.Store) { - gologger.Print().Msgf( + r.Logger.Print().Msgf( "\nListing available %v nuclei tags for %v", config.DefaultConfig.TemplateVersion, config.DefaultConfig.TemplatesDirectory, @@ -100,9 +99,9 @@ func (r *Runner) listAvailableStoreTags(store *loader.Store) { for _, tag := range tagsList { if r.options.JSONL { marshalled, _ := jsoniter.Marshal(tag) - gologger.Silent().Msgf("%s\n", string(marshalled)) + r.Logger.Debug().Msgf("%s", string(marshalled)) } else { - gologger.Silent().Msgf("%s (%d)\n", tag.Key, tag.Value) + r.Logger.Debug().Msgf("%s (%d)", tag.Key, tag.Value) } } } diff --git a/internal/server/nuclei_sdk.go b/internal/server/nuclei_sdk.go index aad337743..022d9ab9b 100644 --- a/internal/server/nuclei_sdk.go +++ b/internal/server/nuclei_sdk.go @@ -41,7 +41,7 @@ type nucleiExecutor struct { engine *core.Engine store *loader.Store options *NucleiExecutorOptions - executorOpts protocols.ExecutorOptions + executorOpts *protocols.ExecutorOptions } type NucleiExecutorOptions struct { @@ -58,6 +58,7 @@ type NucleiExecutorOptions struct { Colorizer aurora.Aurora Parser parser.Parser TemporaryDirectory string + Logger *gologger.Logger } func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) { @@ -66,7 +67,7 @@ func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) { // Create the executor options which will be used throughout the execution // stage by the nuclei engine modules. - executorOpts := protocols.ExecutorOptions{ + executorOpts := &protocols.ExecutorOptions{ Output: opts.Output, Options: opts.Options, Progress: opts.Progress, @@ -85,6 +86,7 @@ func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) { FuzzParamsFrequency: fuzzFreqCache, GlobalMatchers: globalmatchers.New(), FuzzStatsDB: opts.FuzzStatsDB, + Logger: opts.Logger, } if opts.Options.ShouldUseHostError() { @@ -93,7 +95,7 @@ func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) { maxHostError = 100 // auto adjust for fuzzings } if opts.Options.TemplateThreads > maxHostError { - gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", opts.Options.TemplateThreads) + opts.Logger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", opts.Options.TemplateThreads) maxHostError = opts.Options.TemplateThreads } @@ -107,7 +109,7 @@ func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) { executorEngine := core.New(opts.Options) executorEngine.SetExecuterOptions(executorOpts) - workflowLoader, err := parsers.NewLoader(&executorOpts) + workflowLoader, err := parsers.NewLoader(executorOpts) if err != nil { return nil, errors.Wrap(err, "Could not create loader options.") } diff --git a/internal/server/server.go b/internal/server/server.go index 9e297fce2..bc06a1edc 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -112,7 +112,7 @@ func New(options *Options) (*DASTServer, error) { func NewStatsServer(fuzzStatsDB *stats.Tracker) (*DASTServer, error) { server := &DASTServer{ nucleiExecutor: &nucleiExecutor{ - executorOpts: protocols.ExecutorOptions{ + executorOpts: &protocols.ExecutorOptions{ FuzzStatsDB: fuzzStatsDB, }, }, diff --git a/lib/config.go b/lib/config.go index c7746c090..5e96352b5 100644 --- a/lib/config.go +++ b/lib/config.go @@ -19,6 +19,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/utils/vardump" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/headless/engine" "github.com/projectdiscovery/nuclei/v3/pkg/templates/types" + pkgtypes "github.com/projectdiscovery/nuclei/v3/pkg/types" ) // TemplateSources contains template sources @@ -205,7 +206,7 @@ func EnableHeadlessWithOpts(hopts *HeadlessOpts) NucleiSDKOptions { e.opts.UseInstalledChrome = hopts.UseChrome } if engine.MustDisableSandbox() { - gologger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n") + e.Logger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox") } browser, err := engine.New(e.opts) if err != nil { @@ -296,8 +297,8 @@ func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions { if e.opts.ShouldUseHostError() { maxHostError := opts.MaxHostError if e.opts.TemplateThreads > maxHostError { - gologger.Warning().Msg(" The concurrency value is higher than max-host-error") - gologger.Warning().Msgf("Adjusting max-host-error to the concurrency value: %d", e.opts.TemplateThreads) + e.Logger.Warning().Msg("The concurrency value is higher than max-host-error") + e.Logger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", e.opts.TemplateThreads) maxHostError = e.opts.TemplateThreads e.opts.MaxHostError = maxHostError } @@ -419,6 +420,14 @@ func EnableGlobalMatchersTemplates() NucleiSDKOptions { } } +// DisableTemplateCache disables template caching +func DisableTemplateCache() NucleiSDKOptions { + return func(e *NucleiEngine) error { + e.opts.DoNotCacheTemplates = true + return nil + } +} + // EnableFileTemplates allows loading/executing file protocol templates func EnableFileTemplates() NucleiSDKOptions { return func(e *NucleiEngine) error { @@ -527,3 +536,25 @@ func WithResumeFile(file string) NucleiSDKOptions { return nil } } + +// WithLogger allows setting gologger instance +func WithLogger(logger *gologger.Logger) NucleiSDKOptions { + return func(e *NucleiEngine) error { + e.Logger = logger + if e.opts != nil { + e.opts.Logger = logger + } + if e.executerOpts != nil { + e.executerOpts.Logger = logger + } + return nil + } +} + +// WithOptions sets all options at once +func WithOptions(opts *pkgtypes.Options) NucleiSDKOptions { + return func(e *NucleiEngine) error { + e.opts = opts + return nil + } +} diff --git a/lib/multi.go b/lib/multi.go index 1aa870836..3c414116d 100644 --- a/lib/multi.go +++ b/lib/multi.go @@ -14,6 +14,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/ratelimit" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/rs/xid" ) // unsafeOptions are those nuclei objects/instances/types @@ -21,14 +22,14 @@ import ( // hence they are ephemeral and are created on every ExecuteNucleiWithOpts invocation // in ThreadSafeNucleiEngine type unsafeOptions struct { - executerOpts protocols.ExecutorOptions + executerOpts *protocols.ExecutorOptions engine *core.Engine } // createEphemeralObjects creates ephemeral nuclei objects/instances/types func createEphemeralObjects(ctx context.Context, base *NucleiEngine, opts *types.Options) (*unsafeOptions, error) { u := &unsafeOptions{} - u.executerOpts = protocols.ExecutorOptions{ + u.executerOpts = &protocols.ExecutorOptions{ Output: base.customWriter, Options: opts, Progress: base.customProgress, @@ -88,9 +89,11 @@ type ThreadSafeNucleiEngine struct { // whose methods are thread-safe and can be used concurrently // Note: Non-thread-safe methods start with Global prefix func NewThreadSafeNucleiEngineCtx(ctx context.Context, opts ...NucleiSDKOptions) (*ThreadSafeNucleiEngine, error) { + defaultOptions := types.DefaultOptions() + defaultOptions.ExecutionId = xid.New().String() // default options e := &NucleiEngine{ - opts: types.DefaultOptions(), + opts: defaultOptions, mode: threadSafe, } for _, option := range opts { @@ -125,8 +128,8 @@ func (e *ThreadSafeNucleiEngine) GlobalResultCallback(callback func(event *outpu // by invoking this method with different options and targets // Note: Not all options are thread-safe. this method will throw error if you try to use non-thread-safe options func (e *ThreadSafeNucleiEngine) ExecuteNucleiWithOptsCtx(ctx context.Context, targets []string, opts ...NucleiSDKOptions) error { - baseOpts := *e.eng.opts - tmpEngine := &NucleiEngine{opts: &baseOpts, mode: threadSafe} + baseOpts := e.eng.opts.Copy() + tmpEngine := &NucleiEngine{opts: baseOpts, mode: threadSafe} for _, option := range opts { if err := option(tmpEngine); err != nil { return err @@ -142,7 +145,7 @@ func (e *ThreadSafeNucleiEngine) ExecuteNucleiWithOptsCtx(ctx context.Context, t defer closeEphemeralObjects(unsafeOpts) // load templates - workflowLoader, err := workflow.NewLoader(&unsafeOpts.executerOpts) + workflowLoader, err := workflow.NewLoader(unsafeOpts.executerOpts) if err != nil { return errorutil.New("Could not create workflow loader: %s\n", err) } @@ -154,7 +157,7 @@ func (e *ThreadSafeNucleiEngine) ExecuteNucleiWithOptsCtx(ctx context.Context, t } store.Load() - inputProvider := provider.NewSimpleInputProviderWithUrls(targets...) + inputProvider := provider.NewSimpleInputProviderWithUrls(e.eng.opts.ExecutionId, targets...) if len(store.Templates()) == 0 && len(store.Workflows()) == 0 { return ErrNoTemplatesAvailable diff --git a/lib/sdk.go b/lib/sdk.go index a8639b1d6..d1d8314db 100644 --- a/lib/sdk.go +++ b/lib/sdk.go @@ -7,6 +7,7 @@ import ( "io" "sync" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/loader" @@ -28,6 +29,7 @@ import ( "github.com/projectdiscovery/ratelimit" "github.com/projectdiscovery/retryablehttp-go" errorutil "github.com/projectdiscovery/utils/errors" + "github.com/rs/xid" ) // NucleiSDKOptions contains options for nuclei SDK @@ -86,12 +88,15 @@ type NucleiEngine struct { customWriter output.Writer customProgress progress.Progress rc reporting.Client - executerOpts protocols.ExecutorOptions + executerOpts *protocols.ExecutorOptions + + // Logger instance for the engine + Logger *gologger.Logger } // LoadAllTemplates loads all nuclei template based on given options func (e *NucleiEngine) LoadAllTemplates() error { - workflowLoader, err := workflow.NewLoader(&e.executerOpts) + workflowLoader, err := workflow.NewLoader(e.executerOpts) if err != nil { return errorutil.New("Could not create workflow loader: %s\n", err) } @@ -126,9 +131,9 @@ func (e *NucleiEngine) GetWorkflows() []*templates.Template { func (e *NucleiEngine) LoadTargets(targets []string, probeNonHttp bool) { for _, target := range targets { if probeNonHttp { - _ = e.inputProvider.SetWithProbe(target, e.httpxClient) + _ = e.inputProvider.SetWithProbe(e.opts.ExecutionId, target, e.httpxClient) } else { - e.inputProvider.Set(target) + e.inputProvider.Set(e.opts.ExecutionId, target) } } } @@ -138,9 +143,9 @@ func (e *NucleiEngine) LoadTargetsFromReader(reader io.Reader, probeNonHttp bool buff := bufio.NewScanner(reader) for buff.Scan() { if probeNonHttp { - _ = e.inputProvider.SetWithProbe(buff.Text(), e.httpxClient) + _ = e.inputProvider.SetWithProbe(e.opts.ExecutionId, buff.Text(), e.httpxClient) } else { - e.inputProvider.Set(buff.Text()) + e.inputProvider.Set(e.opts.ExecutionId, buff.Text()) } } } @@ -163,7 +168,7 @@ func (e *NucleiEngine) LoadTargetsWithHttpData(filePath string, filemode string) // GetExecuterOptions returns the nuclei executor options func (e *NucleiEngine) GetExecuterOptions() *protocols.ExecutorOptions { - return &e.executerOpts + return e.executerOpts } // ParseTemplate parses a template from given data @@ -231,7 +236,7 @@ func (e *NucleiEngine) closeInternal() { // Close all resources used by nuclei engine func (e *NucleiEngine) Close() { e.closeInternal() - protocolinit.Close() + protocolinit.Close(e.opts.ExecutionId) } // ExecuteCallbackWithCtx executes templates on targets and calls callback on each result(only if results are found) @@ -306,8 +311,10 @@ func (e *NucleiEngine) Store() *loader.Store { // NewNucleiEngineCtx creates a new nuclei engine instance with given context func NewNucleiEngineCtx(ctx context.Context, options ...NucleiSDKOptions) (*NucleiEngine, error) { // default options + defaultOptions := types.DefaultOptions() + defaultOptions.ExecutionId = xid.New().String() e := &NucleiEngine{ - opts: types.DefaultOptions(), + opts: defaultOptions, mode: singleInstance, ctx: ctx, } @@ -327,6 +334,11 @@ func NewNucleiEngine(options ...NucleiSDKOptions) (*NucleiEngine, error) { return NewNucleiEngineCtx(context.Background(), options...) } +// GetParser returns the template parser with cache +func (e *NucleiEngine) GetParser() *templates.Parser { + return e.parser +} + // wait for a waitgroup to finish func wait(wg *sync.WaitGroup) <-chan struct{} { ch := make(chan struct{}) diff --git a/lib/sdk_private.go b/lib/sdk_private.go index c0d394acc..659187b20 100644 --- a/lib/sdk_private.go +++ b/lib/sdk_private.go @@ -8,6 +8,7 @@ import ( "time" "github.com/projectdiscovery/nuclei/v3/pkg/input" + "github.com/projectdiscovery/nuclei/v3/pkg/reporting" "github.com/logrusorgru/aurora" "github.com/pkg/errors" @@ -29,7 +30,6 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolinit" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/http/httpclientpool" - "github.com/projectdiscovery/nuclei/v3/pkg/reporting" "github.com/projectdiscovery/nuclei/v3/pkg/templates" "github.com/projectdiscovery/nuclei/v3/pkg/testutils" "github.com/projectdiscovery/nuclei/v3/pkg/types" @@ -37,8 +37,6 @@ import ( "github.com/projectdiscovery/ratelimit" ) -var sharedInit *sync.Once - // applyRequiredDefaults to options func (e *NucleiEngine) applyRequiredDefaults(ctx context.Context) { mockoutput := testutils.NewMockOutputWriter(e.opts.OmitTemplate) @@ -98,27 +96,39 @@ func (e *NucleiEngine) applyRequiredDefaults(ctx context.Context) { // init func (e *NucleiEngine) init(ctx context.Context) error { + // Set a default logger if one isn't provided in the options + if e.opts.Logger != nil { + e.Logger = e.opts.Logger + } else { + e.opts.Logger = &gologger.Logger{} + } + e.Logger = e.opts.Logger + if e.opts.Verbose { - gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose) + e.Logger.SetMaxLevel(levels.LevelVerbose) } else if e.opts.Debug { - gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug) + e.Logger.SetMaxLevel(levels.LevelDebug) } else if e.opts.Silent { - gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) + e.Logger.SetMaxLevel(levels.LevelSilent) } if err := runner.ValidateOptions(e.opts); err != nil { return err } - e.parser = templates.NewParser() - - if sharedInit == nil || protocolstate.ShouldInit() { - sharedInit = &sync.Once{} + if e.opts.Parser != nil { + if op, ok := e.opts.Parser.(*templates.Parser); ok { + e.parser = op + } } - sharedInit.Do(func() { + if e.parser == nil { + e.parser = templates.NewParser() + } + + if protocolstate.ShouldInit(e.opts.ExecutionId) { _ = protocolinit.Init(e.opts) - }) + } if e.opts.ProxyInternal && e.opts.AliveHttpProxy != "" || e.opts.AliveSocksProxy != "" { httpclient, err := httpclientpool.Get(e.opts, &httpclientpool.Configuration{}) @@ -160,7 +170,7 @@ func (e *NucleiEngine) init(ctx context.Context) error { e.catalog = disk.NewCatalog(config.DefaultConfig.TemplatesDirectory) } - e.executerOpts = protocols.ExecutorOptions{ + e.executerOpts = &protocols.ExecutorOptions{ Output: e.customWriter, Options: e.opts, Progress: e.customProgress, @@ -173,12 +183,13 @@ func (e *NucleiEngine) init(ctx context.Context) error { Browser: e.browserInstance, Parser: e.parser, InputHelper: input.NewHelper(), + Logger: e.opts.Logger, } if e.opts.ShouldUseHostError() && e.hostErrCache != nil { e.executerOpts.HostErrorsCache = e.hostErrCache } if len(e.opts.SecretsFile) > 0 { - authTmplStore, err := runner.GetAuthTmplStore(*e.opts, e.catalog, e.executerOpts) + authTmplStore, err := runner.GetAuthTmplStore(e.opts, e.catalog, e.executerOpts) if err != nil { return errors.Wrap(err, "failed to load dynamic auth templates") } diff --git a/pkg/catalog/config/ignorefile.go b/pkg/catalog/config/ignorefile.go index 14c0ec30f..8ac7211ed 100644 --- a/pkg/catalog/config/ignorefile.go +++ b/pkg/catalog/config/ignorefile.go @@ -2,6 +2,7 @@ package config import ( "os" + "runtime/debug" "github.com/projectdiscovery/gologger" "gopkg.in/yaml.v2" @@ -17,7 +18,7 @@ type IgnoreFile struct { func ReadIgnoreFile() IgnoreFile { file, err := os.Open(DefaultConfig.GetIgnoreFilePath()) if err != nil { - gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n", err) + gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n%s\n", err, string(debug.Stack())) return IgnoreFile{} } defer func() { diff --git a/pkg/catalog/config/nucleiconfig.go b/pkg/catalog/config/nucleiconfig.go index ebfbb77a3..1f43d0c16 100644 --- a/pkg/catalog/config/nucleiconfig.go +++ b/pkg/catalog/config/nucleiconfig.go @@ -8,6 +8,7 @@ import ( "path/filepath" "slices" "strings" + "sync" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" @@ -40,15 +41,18 @@ type Config struct { // local cache of nuclei version check endpoint // these fields are only update during nuclei version check // TODO: move these fields to a separate unexported struct as they are not meant to be used directly - LatestNucleiVersion string `json:"nuclei-latest-version"` - LatestNucleiTemplatesVersion string `json:"nuclei-templates-latest-version"` - LatestNucleiIgnoreHash string `json:"nuclei-latest-ignore-hash,omitempty"` + LatestNucleiVersion string `json:"nuclei-latest-version"` + LatestNucleiTemplatesVersion string `json:"nuclei-templates-latest-version"` + LatestNucleiIgnoreHash string `json:"nuclei-latest-ignore-hash,omitempty"` + Logger *gologger.Logger `json:"-"` // logger // internal / unexported fields disableUpdates bool `json:"-"` // disable updates both version check and template updates homeDir string `json:"-"` // User Home Directory configDir string `json:"-"` // Nuclei Global Config Directory debugArgs []string `json:"-"` // debug args + + m sync.Mutex } // IsCustomTemplate determines whether a given template is custom-built or part of the official Nuclei templates. @@ -103,21 +107,29 @@ func (c *Config) GetTemplateDir() string { // DisableUpdateCheck disables update check and template updates func (c *Config) DisableUpdateCheck() { + c.m.Lock() + defer c.m.Unlock() c.disableUpdates = true } // CanCheckForUpdates returns true if update check is enabled func (c *Config) CanCheckForUpdates() bool { + c.m.Lock() + defer c.m.Unlock() return !c.disableUpdates } // NeedsTemplateUpdate returns true if template installation/update is required func (c *Config) NeedsTemplateUpdate() bool { + c.m.Lock() + defer c.m.Unlock() return !c.disableUpdates && (c.TemplateVersion == "" || IsOutdatedVersion(c.TemplateVersion, c.LatestNucleiTemplatesVersion) || !fileutil.FolderExists(c.TemplatesDirectory)) } // NeedsIgnoreFileUpdate returns true if Ignore file hash is different (aka ignore file is outdated) func (c *Config) NeedsIgnoreFileUpdate() bool { + c.m.Lock() + defer c.m.Unlock() return c.NucleiIgnoreHash == "" || c.NucleiIgnoreHash != c.LatestNucleiIgnoreHash } @@ -209,7 +221,7 @@ func (c *Config) GetCacheDir() string { func (c *Config) SetConfigDir(dir string) { c.configDir = dir if err := c.createConfigDirIfNotExists(); err != nil { - gologger.Fatal().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err) + c.Logger.Fatal().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err) } // if folder already exists read config or create new @@ -217,7 +229,7 @@ func (c *Config) SetConfigDir(dir string) { // create new config applyDefaultConfig() if err2 := c.WriteTemplatesConfig(); err2 != nil { - gologger.Fatal().Msgf("Could not create nuclei config file at %s: %s", c.getTemplatesConfigFilePath(), err2) + c.Logger.Fatal().Msgf("Could not create nuclei config file at %s: %s", c.getTemplatesConfigFilePath(), err2) } } @@ -317,14 +329,14 @@ func (c *Config) createConfigDirIfNotExists() error { // to the current config directory func (c *Config) copyIgnoreFile() { if err := c.createConfigDirIfNotExists(); err != nil { - gologger.Error().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err) + c.Logger.Error().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err) return } ignoreFilePath := c.GetIgnoreFilePath() if !fileutil.FileExists(ignoreFilePath) { // copy ignore file from default config directory if err := fileutil.CopyFile(filepath.Join(folderutil.AppConfigDirOrDefault(FallbackConfigFolderName, BinaryName), NucleiIgnoreFileName), ignoreFilePath); err != nil { - gologger.Error().Msgf("Could not copy nuclei ignore file at %s: %s", ignoreFilePath, err) + c.Logger.Error().Msgf("Could not copy nuclei ignore file at %s: %s", ignoreFilePath, err) } } } @@ -380,6 +392,7 @@ func init() { DefaultConfig = &Config{ homeDir: folderutil.HomeDirOrDefault(""), configDir: ConfigDir, + Logger: gologger.DefaultLogger, } // when enabled will log events in more verbosity than -v or -debug diff --git a/pkg/catalog/config/template.go b/pkg/catalog/config/template.go index ecb93e283..3d7b33de5 100644 --- a/pkg/catalog/config/template.go +++ b/pkg/catalog/config/template.go @@ -7,7 +7,6 @@ import ( "path/filepath" "strings" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/templates/extensions" fileutil "github.com/projectdiscovery/utils/file" stringsutil "github.com/projectdiscovery/utils/strings" @@ -98,7 +97,7 @@ func GetNucleiTemplatesIndex() (map[string]string, error) { return index, nil } } - gologger.Error().Msgf("failed to read index file creating new one: %v", err) + DefaultConfig.Logger.Error().Msgf("failed to read index file creating new one: %v", err) } ignoreDirs := DefaultConfig.GetAllCustomTemplateDirs() @@ -109,7 +108,7 @@ func GetNucleiTemplatesIndex() (map[string]string, error) { } err := filepath.WalkDir(DefaultConfig.TemplatesDirectory, func(path string, d os.DirEntry, err error) error { if err != nil { - gologger.Verbose().Msgf("failed to walk path=%v err=%v", path, err) + DefaultConfig.Logger.Verbose().Msgf("failed to walk path=%v err=%v", path, err) return nil } if d.IsDir() || !IsTemplate(path) || stringsutil.ContainsAny(path, ignoreDirs...) { @@ -118,7 +117,7 @@ func GetNucleiTemplatesIndex() (map[string]string, error) { // get template id from file id, err := getTemplateID(path) if err != nil || id == "" { - gologger.Verbose().Msgf("failed to get template id from file=%v got id=%v err=%v", path, id, err) + DefaultConfig.Logger.Verbose().Msgf("failed to get template id from file=%v got id=%v err=%v", path, id, err) return nil } index[id] = path diff --git a/pkg/catalog/disk/find.go b/pkg/catalog/disk/find.go index 0e4021b87..7a70c1bc1 100644 --- a/pkg/catalog/disk/find.go +++ b/pkg/catalog/disk/find.go @@ -8,7 +8,6 @@ import ( "github.com/logrusorgru/aurora" "github.com/pkg/errors" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" stringsutil "github.com/projectdiscovery/utils/strings" updateutils "github.com/projectdiscovery/utils/update" @@ -84,7 +83,7 @@ func (c *DiskCatalog) GetTemplatePath(target string) ([]string, error) { absPath = BackwardsCompatiblePaths(c.templatesDirectory, target) if absPath != target && strings.TrimPrefix(absPath, c.templatesDirectory+string(filepath.Separator)) != target { if config.DefaultConfig.LogAllEvents { - gologger.DefaultLogger.Print().Msgf("[%v] requested Template path %s is deprecated, please update to %s\n", aurora.Yellow("WRN").String(), target, absPath) + config.DefaultConfig.Logger.Print().Msgf("[%v] requested Template path %s is deprecated, please update to %s\n", aurora.Yellow("WRN").String(), target, absPath) } deprecatedPathsCounter++ } @@ -302,6 +301,6 @@ func PrintDeprecatedPathsMsgIfApplicable(isSilent bool) { return } if deprecatedPathsCounter > 0 && !isSilent { - gologger.Print().Msgf("[%v] Found %v template[s] loaded with deprecated paths, update before v3 for continued support.\n", aurora.Yellow("WRN").String(), deprecatedPathsCounter) + config.DefaultConfig.Logger.Print().Msgf("[%v] Found %v template[s] loaded with deprecated paths, update before v3 for continued support.\n", aurora.Yellow("WRN").String(), deprecatedPathsCounter) } } diff --git a/pkg/catalog/loader/ai_loader.go b/pkg/catalog/loader/ai_loader.go index ce12e90b1..998d2b0b9 100644 --- a/pkg/catalog/loader/ai_loader.go +++ b/pkg/catalog/loader/ai_loader.go @@ -10,7 +10,6 @@ import ( "strings" "github.com/alecthomas/chroma/quick" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/retryablehttp-go" @@ -57,8 +56,8 @@ func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, e return nil, errorutil.New("Failed to generate template: %v", err) } - gologger.Info().Msgf("Generated template available at: https://cloud.projectdiscovery.io/templates/%s", templateID) - gologger.Info().Msgf("Generated template path: %s", templateFile) + options.Logger.Info().Msgf("Generated template available at: https://cloud.projectdiscovery.io/templates/%s", templateID) + options.Logger.Info().Msgf("Generated template path: %s", templateFile) // Check if we should display the template // This happens when: @@ -76,7 +75,7 @@ func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, e template = buf.String() } } - gologger.Silent().Msgf("\n%s", template) + options.Logger.Debug().Msgf("\n%s", template) // FIXME: // we should not be exiting the program here // but we need to find a better way to handle this diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 98039117d..2c3403240 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -7,7 +7,6 @@ import ( "os" "sort" "strings" - "sync" "github.com/logrusorgru/aurora" "github.com/pkg/errors" @@ -18,6 +17,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/keys" "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" + "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/templates" templateTypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types" "github.com/projectdiscovery/nuclei/v3/pkg/types" @@ -27,7 +27,9 @@ import ( errorutil "github.com/projectdiscovery/utils/errors" sliceutil "github.com/projectdiscovery/utils/slice" stringsutil "github.com/projectdiscovery/utils/strings" + syncutil "github.com/projectdiscovery/utils/sync" urlutil "github.com/projectdiscovery/utils/url" + "github.com/rs/xid" ) const ( @@ -65,7 +67,8 @@ type Config struct { IncludeConditions []string Catalog catalog.Catalog - ExecutorOptions protocols.ExecutorOptions + ExecutorOptions *protocols.ExecutorOptions + Logger *gologger.Logger } // Store is a storage for loaded nuclei templates @@ -82,13 +85,15 @@ type Store struct { preprocessor templates.Preprocessor + logger *gologger.Logger + // NotFoundCallback is called for each not found template // This overrides error handling for not found templates NotFoundCallback func(template string) bool } // NewConfig returns a new loader config -func NewConfig(options *types.Options, catalog catalog.Catalog, executerOpts protocols.ExecutorOptions) *Config { +func NewConfig(options *types.Options, catalog catalog.Catalog, executerOpts *protocols.ExecutorOptions) *Config { loaderConfig := Config{ Templates: options.Templates, Workflows: options.Workflows, @@ -111,6 +116,7 @@ func NewConfig(options *types.Options, catalog catalog.Catalog, executerOpts pro Catalog: catalog, ExecutorOptions: executerOpts, AITemplatePrompt: options.AITemplatePrompt, + Logger: options.Logger, } loaderConfig.RemoteTemplateDomainList = append(loaderConfig.RemoteTemplateDomainList, TrustedTemplateDomains...) return &loaderConfig @@ -145,6 +151,7 @@ func New(cfg *Config) (*Store, error) { }, cfg.Catalog), finalTemplates: cfg.Templates, finalWorkflows: cfg.Workflows, + logger: cfg.Logger, } // Do a check to see if we have URLs in templates flag, if so @@ -238,8 +245,8 @@ func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error) return nil, err } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() return io.ReadAll(resp.Body) } else { return os.ReadFile(uri) @@ -295,11 +302,11 @@ func (store *Store) LoadTemplatesOnlyMetadata() error { if strings.Contains(err.Error(), templates.ErrExcluded.Error()) { stats.Increment(templates.TemplatesExcludedStats) if config.DefaultConfig.LogAllEvents { - gologger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error()) + store.logger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error()) } continue } - gologger.Warning().Msg(err.Error()) + store.logger.Warning().Msg(err.Error()) } } parserItem, ok := store.config.ExecutorOptions.Parser.(*templates.Parser) @@ -358,15 +365,13 @@ func (store *Store) ValidateTemplates() error { func (store *Store) areWorkflowsValid(filteredWorkflowPaths map[string]struct{}) bool { return store.areWorkflowOrTemplatesValid(filteredWorkflowPaths, true, func(templatePath string, tagFilter *templates.TagFilter) (bool, error) { - return false, nil - // return store.config.ExecutorOptions.Parser.LoadWorkflow(templatePath, store.config.Catalog) + return store.config.ExecutorOptions.Parser.LoadWorkflow(templatePath, store.config.Catalog) }) } func (store *Store) areTemplatesValid(filteredTemplatePaths map[string]struct{}) bool { return store.areWorkflowOrTemplatesValid(filteredTemplatePaths, false, func(templatePath string, tagFilter *templates.TagFilter) (bool, error) { - return false, nil - // return store.config.ExecutorOptions.Parser.LoadTemplate(templatePath, store.tagFilter, nil, store.config.Catalog) + return store.config.ExecutorOptions.Parser.LoadTemplate(templatePath, store.tagFilter, nil, store.config.Catalog) }) } @@ -375,7 +380,7 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string for templatePath := range filteredTemplatePaths { if _, err := load(templatePath, store.tagFilter); err != nil { - if isParsingError("Error occurred loading template %s: %s\n", templatePath, err) { + if isParsingError(store, "Error occurred loading template %s: %s\n", templatePath, err) { areTemplatesValid = false continue } @@ -383,7 +388,7 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string template, err := templates.Parse(templatePath, store.preprocessor, store.config.ExecutorOptions) if err != nil { - if isParsingError("Error occurred parsing template %s: %s\n", templatePath, err) { + if isParsingError(store, "Error occurred parsing template %s: %s\n", templatePath, err) { areTemplatesValid = false continue } @@ -408,7 +413,7 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string // TODO: until https://github.com/projectdiscovery/nuclei-templates/issues/11324 is deployed // disable strict validation to allow GH actions to run // areTemplatesValid = false - gologger.Warning().Msgf("Found duplicate template ID during validation '%s' => '%s': %s\n", templatePath, existingTemplatePath, template.ID) + store.logger.Warning().Msgf("Found duplicate template ID during validation '%s' => '%s': %s\n", templatePath, existingTemplatePath, template.ID) } if !isWorkflow && len(template.Workflows) > 0 { continue @@ -431,7 +436,7 @@ func areWorkflowTemplatesValid(store *Store, workflows []*workflows.WorkflowTemp } _, err := store.config.Catalog.GetTemplatePath(workflow.Template) if err != nil { - if isParsingError("Error occurred loading template %s: %s\n", workflow.Template, err) { + if isParsingError(store, "Error occurred loading template %s: %s\n", workflow.Template, err) { return false } } @@ -439,14 +444,14 @@ func areWorkflowTemplatesValid(store *Store, workflows []*workflows.WorkflowTemp return true } -func isParsingError(message string, template string, err error) bool { +func isParsingError(store *Store, message string, template string, err error) bool { if errors.Is(err, templates.ErrExcluded) { return false } if errors.Is(err, templates.ErrCreateTemplateExecutor) { return false } - gologger.Error().Msgf(message, template, err) + store.logger.Error().Msgf(message, template, err) return true } @@ -465,12 +470,12 @@ func (store *Store) LoadWorkflows(workflowsList []string) []*templates.Template for workflowPath := range workflowPathMap { loaded, err := store.config.ExecutorOptions.Parser.LoadWorkflow(workflowPath, store.config.Catalog) if err != nil { - gologger.Warning().Msgf("Could not load workflow %s: %s\n", workflowPath, err) + store.logger.Warning().Msgf("Could not load workflow %s: %s\n", workflowPath, err) } if loaded { parsed, err := templates.Parse(workflowPath, store.preprocessor, store.config.ExecutorOptions) if err != nil { - gologger.Warning().Msgf("Could not parse workflow %s: %s\n", workflowPath, err) + store.logger.Warning().Msgf("Could not parse workflow %s: %s\n", workflowPath, err) } else if parsed != nil { loadedWorkflows = append(loadedWorkflows, parsed) } @@ -502,10 +507,22 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ } } - var wgLoadTemplates sync.WaitGroup + wgLoadTemplates, errWg := syncutil.New(syncutil.WithSize(50)) + if errWg != nil { + panic("could not create wait group") + } + + if store.config.ExecutorOptions.Options.ExecutionId == "" { + store.config.ExecutorOptions.Options.ExecutionId = xid.New().String() + } + + dialers := protocolstate.GetDialersWithId(store.config.ExecutorOptions.Options.ExecutionId) + if dialers == nil { + panic("dialers with executionId " + store.config.ExecutorOptions.Options.ExecutionId + " not found") + } for templatePath := range templatePathMap { - wgLoadTemplates.Add(1) + wgLoadTemplates.Add() go func(templatePath string) { defer wgLoadTemplates.Done() @@ -517,7 +534,7 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ if !errors.Is(err, templates.ErrIncompatibleWithOfflineMatching) { stats.Increment(templates.RuntimeWarningsStats) } - gologger.Warning().Msgf("Could not parse template %s: %s\n", templatePath, err) + store.logger.Warning().Msgf("Could not parse template %s: %s\n", templatePath, err) } else if parsed != nil { if !parsed.Verified && store.config.ExecutorOptions.Options.DisableUnsignedTemplates { // skip unverified templates when prompted to @@ -552,13 +569,13 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ // donot include headless template in final list if headless flag is not set stats.Increment(templates.ExcludedHeadlessTmplStats) if config.DefaultConfig.LogAllEvents { - gologger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) + store.logger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) } } else if len(parsed.RequestsCode) > 0 && !store.config.ExecutorOptions.Options.EnableCodeTemplates { // donot include 'Code' protocol custom template in final list if code flag is not set stats.Increment(templates.ExcludedCodeTmplStats) if config.DefaultConfig.LogAllEvents { - gologger.Print().Msgf("[%v] Code flag is required for code protocol template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) + store.logger.Print().Msgf("[%v] Code flag is required for code protocol template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) } } else if len(parsed.RequestsCode) > 0 && !parsed.Verified && len(parsed.Workflows) == 0 { // donot include unverified 'Code' protocol custom template in final list @@ -566,12 +583,12 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ // these will be skipped so increment skip counter stats.Increment(templates.SkippedUnsignedStats) if config.DefaultConfig.LogAllEvents { - gologger.Print().Msgf("[%v] Tampered/Unsigned template at %v.\n", aurora.Yellow("WRN").String(), templatePath) + store.logger.Print().Msgf("[%v] Tampered/Unsigned template at %v.\n", aurora.Yellow("WRN").String(), templatePath) } } else if parsed.IsFuzzing() && !store.config.ExecutorOptions.Options.DAST { stats.Increment(templates.ExludedDastTmplStats) if config.DefaultConfig.LogAllEvents { - gologger.Print().Msgf("[%v] -dast flag is required for DAST template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) + store.logger.Print().Msgf("[%v] -dast flag is required for DAST template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) } } else { loadTemplate(parsed) @@ -582,11 +599,11 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ if strings.Contains(err.Error(), templates.ErrExcluded.Error()) { stats.Increment(templates.TemplatesExcludedStats) if config.DefaultConfig.LogAllEvents { - gologger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error()) + store.logger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error()) } return } - gologger.Warning().Msg(err.Error()) + store.logger.Warning().Msg(err.Error()) } }(templatePath) } @@ -642,7 +659,7 @@ func workflowContainsProtocol(workflow []*workflows.WorkflowTemplate) bool { func (s *Store) logErroredTemplates(erred map[string]error) { for template, err := range erred { if s.NotFoundCallback == nil || !s.NotFoundCallback(template) { - gologger.Error().Msgf("Could not find template '%s': %s", template, err) + s.logger.Error().Msgf("Could not find template '%s': %s", template, err) } } } diff --git a/pkg/catalog/loader/remote_loader.go b/pkg/catalog/loader/remote_loader.go index 749d19d91..ccd5c27f0 100644 --- a/pkg/catalog/loader/remote_loader.go +++ b/pkg/catalog/loader/remote_loader.go @@ -5,13 +5,16 @@ import ( "fmt" "net/url" "strings" + "sync" "github.com/pkg/errors" "github.com/projectdiscovery/nuclei/v3/pkg/templates/extensions" "github.com/projectdiscovery/nuclei/v3/pkg/utils" "github.com/projectdiscovery/retryablehttp-go" + sliceutil "github.com/projectdiscovery/utils/slice" stringsutil "github.com/projectdiscovery/utils/strings" + syncutil "github.com/projectdiscovery/utils/sync" ) type ContentType string @@ -28,67 +31,73 @@ type RemoteContent struct { } func getRemoteTemplatesAndWorkflows(templateURLs, workflowURLs, remoteTemplateDomainList []string) ([]string, []string, error) { - remoteContentChannel := make(chan RemoteContent) + var ( + err error + muErr sync.Mutex + ) + remoteTemplateList := sliceutil.NewSyncSlice[string]() + remoteWorkFlowList := sliceutil.NewSyncSlice[string]() - for _, templateURL := range templateURLs { - go getRemoteContent(templateURL, remoteTemplateDomainList, remoteContentChannel, Template) - } - for _, workflowURL := range workflowURLs { - go getRemoteContent(workflowURL, remoteTemplateDomainList, remoteContentChannel, Workflow) + awg, errAwg := syncutil.New(syncutil.WithSize(50)) + if errAwg != nil { + return nil, nil, errAwg } - var remoteTemplateList []string - var remoteWorkFlowList []string - var err error - for i := 0; i < (len(templateURLs) + len(workflowURLs)); i++ { - remoteContent := <-remoteContentChannel + loadItem := func(URL string, contentType ContentType) { + defer awg.Done() + + remoteContent := getRemoteContent(URL, remoteTemplateDomainList, contentType) if remoteContent.Error != nil { + muErr.Lock() if err != nil { err = errors.New(remoteContent.Error.Error() + ": " + err.Error()) } else { err = remoteContent.Error } + muErr.Unlock() } else { switch remoteContent.Type { case Template: - remoteTemplateList = append(remoteTemplateList, remoteContent.Content...) + remoteTemplateList.Append(remoteContent.Content...) case Workflow: - remoteWorkFlowList = append(remoteWorkFlowList, remoteContent.Content...) + remoteWorkFlowList.Append(remoteContent.Content...) } } } - return remoteTemplateList, remoteWorkFlowList, err + + for _, templateURL := range templateURLs { + awg.Add() + go loadItem(templateURL, Template) + } + for _, workflowURL := range workflowURLs { + awg.Add() + go loadItem(workflowURL, Workflow) + } + + awg.Wait() + + return remoteTemplateList.Slice, remoteWorkFlowList.Slice, err } -func getRemoteContent(URL string, remoteTemplateDomainList []string, remoteContentChannel chan<- RemoteContent, contentType ContentType) { +func getRemoteContent(URL string, remoteTemplateDomainList []string, contentType ContentType) RemoteContent { if err := validateRemoteTemplateURL(URL, remoteTemplateDomainList); err != nil { - remoteContentChannel <- RemoteContent{ - Error: err, - } - return + return RemoteContent{Error: err} } if strings.HasPrefix(URL, "http") && stringsutil.HasSuffixAny(URL, extensions.YAML) { - remoteContentChannel <- RemoteContent{ + return RemoteContent{ Content: []string{URL}, Type: contentType, } - return } response, err := retryablehttp.DefaultClient().Get(URL) if err != nil { - remoteContentChannel <- RemoteContent{ - Error: err, - } - return + return RemoteContent{Error: err} } defer func() { - _ = response.Body.Close() - }() + _ = response.Body.Close() + }() if response.StatusCode < 200 || response.StatusCode > 299 { - remoteContentChannel <- RemoteContent{ - Error: fmt.Errorf("get \"%s\": unexpect status %d", URL, response.StatusCode), - } - return + return RemoteContent{Error: fmt.Errorf("get \"%s\": unexpect status %d", URL, response.StatusCode)} } scanner := bufio.NewScanner(response.Body) @@ -100,23 +109,17 @@ func getRemoteContent(URL string, remoteTemplateDomainList []string, remoteConte } if utils.IsURL(text) { if err := validateRemoteTemplateURL(text, remoteTemplateDomainList); err != nil { - remoteContentChannel <- RemoteContent{ - Error: err, - } - return + return RemoteContent{Error: err} } } templateList = append(templateList, text) } if err := scanner.Err(); err != nil { - remoteContentChannel <- RemoteContent{ - Error: errors.Wrap(err, "get \"%s\""), - } - return + return RemoteContent{Error: errors.Wrap(err, "get \"%s\"")} } - remoteContentChannel <- RemoteContent{ + return RemoteContent{ Content: templateList, Type: contentType, } diff --git a/pkg/core/engine.go b/pkg/core/engine.go index 1b4155bbb..0a412b6fc 100644 --- a/pkg/core/engine.go +++ b/pkg/core/engine.go @@ -1,6 +1,7 @@ package core import ( + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/types" @@ -17,14 +18,16 @@ import ( type Engine struct { workPool *WorkPool options *types.Options - executerOpts protocols.ExecutorOptions + executerOpts *protocols.ExecutorOptions Callback func(*output.ResultEvent) // Executed on results + Logger *gologger.Logger } // New returns a new Engine instance func New(options *types.Options) *Engine { engine := &Engine{ options: options, + Logger: options.Logger, } engine.workPool = engine.GetWorkPool() return engine @@ -47,12 +50,12 @@ func (e *Engine) GetWorkPool() *WorkPool { // SetExecuterOptions sets the executer options for the engine. This is required // before using the engine to perform any execution. -func (e *Engine) SetExecuterOptions(options protocols.ExecutorOptions) { +func (e *Engine) SetExecuterOptions(options *protocols.ExecutorOptions) { e.executerOpts = options } // ExecuterOptions returns protocols.ExecutorOptions for nuclei engine. -func (e *Engine) ExecuterOptions() protocols.ExecutorOptions { +func (e *Engine) ExecuterOptions() *protocols.ExecutorOptions { return e.executerOpts } diff --git a/pkg/core/execute_options.go b/pkg/core/execute_options.go index fae26b456..df1fe1435 100644 --- a/pkg/core/execute_options.go +++ b/pkg/core/execute_options.go @@ -5,7 +5,6 @@ import ( "sync" "sync/atomic" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/input/provider" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs" @@ -50,7 +49,7 @@ func (e *Engine) ExecuteScanWithOpts(ctx context.Context, templatesList []*templ totalReqAfterClustering := getRequestCount(finalTemplates) * int(target.Count()) if !noCluster && totalReqAfterClustering < totalReqBeforeCluster { - gologger.Info().Msgf("Templates clustered: %d (Reduced %d Requests)", clusterCount, totalReqBeforeCluster-totalReqAfterClustering) + e.Logger.Info().Msgf("Templates clustered: %d (Reduced %d Requests)", clusterCount, totalReqBeforeCluster-totalReqAfterClustering) } // 0 matches means no templates were found in the directory diff --git a/pkg/core/executors.go b/pkg/core/executors.go index 05430233b..e83aed57e 100644 --- a/pkg/core/executors.go +++ b/pkg/core/executors.go @@ -5,7 +5,6 @@ import ( "sync" "sync/atomic" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/input/provider" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs" "github.com/projectdiscovery/nuclei/v3/pkg/scan" @@ -38,7 +37,7 @@ func (e *Engine) executeAllSelfContained(ctx context.Context, alltemplates []*te match, err = template.Executer.Execute(ctx) } if err != nil { - gologger.Warning().Msgf("[%s] Could not execute step (self-contained): %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err) + e.options.Logger.Warning().Msgf("[%s] Could not execute step (self-contained): %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), err) } results.CompareAndSwap(false, match) }(v) @@ -88,13 +87,13 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ // skips indexes lower than the minimum in-flight at interruption time var skip bool if resumeFromInfo.Completed { // the template was completed - gologger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Template already completed\n", template.ID, scannedValue.Input) + e.options.Logger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Template already completed", template.ID, scannedValue.Input) skip = true } else if index < resumeFromInfo.SkipUnder { // index lower than the sliding window (bulk-size) - gologger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Target already processed\n", template.ID, scannedValue.Input) + e.options.Logger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Target already processed", template.ID, scannedValue.Input) skip = true } else if _, isInFlight := resumeFromInfo.InFlight[index]; isInFlight { // the target wasn't completed successfully - gologger.Debug().Msgf("[%s] Repeating \"%s\": Resume - Target wasn't completed\n", template.ID, scannedValue.Input) + e.options.Logger.Debug().Msgf("[%s] Repeating \"%s\": Resume - Target wasn't completed", template.ID, scannedValue.Input) // skip is already false, but leaving it here for clarity skip = false } else if index > resumeFromInfo.DoAbove { // index above the sliding window (bulk-size) @@ -140,7 +139,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ } } if err != nil { - gologger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) + e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) } results.CompareAndSwap(false, match) }(index, skip, scannedValue) @@ -206,7 +205,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t } } if err != nil { - gologger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) + e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) } results.CompareAndSwap(false, match) }(tpl, target, sg) diff --git a/pkg/fuzz/analyzers/time/time_delay.go b/pkg/fuzz/analyzers/time/time_delay.go index 7349be935..d37b83e7c 100644 --- a/pkg/fuzz/analyzers/time/time_delay.go +++ b/pkg/fuzz/analyzers/time/time_delay.go @@ -61,7 +61,6 @@ func checkTimingDependency( var requestsSent []requestsSentMetadata for requestsLeft > 0 { - isCorrelationPossible, delayRecieved, err := sendRequestAndTestConfidence(regression, highSleepTimeSeconds, requestSender, baselineDelay) if err != nil { return false, "", err diff --git a/pkg/fuzz/dataformat/multipart.go b/pkg/fuzz/dataformat/multipart.go index 20f25a6e7..97af6207f 100644 --- a/pkg/fuzz/dataformat/multipart.go +++ b/pkg/fuzz/dataformat/multipart.go @@ -143,8 +143,8 @@ func (m *MultiPartForm) Decode(data string) (KV, error) { return KV{}, err } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() buffer := new(bytes.Buffer) if _, err := buffer.ReadFrom(file); err != nil { diff --git a/pkg/input/provider/http/multiformat.go b/pkg/input/provider/http/multiformat.go index a2440c36d..ee8cb6809 100644 --- a/pkg/input/provider/http/multiformat.go +++ b/pkg/input/provider/http/multiformat.go @@ -115,17 +115,17 @@ func (i *HttpInputProvider) Iterate(callback func(value *contextargs.MetaInput) // Set adds item to input provider // No-op for this provider -func (i *HttpInputProvider) Set(value string) {} +func (i *HttpInputProvider) Set(_ string, value string) {} // SetWithProbe adds item to input provider with http probing // No-op for this provider -func (i *HttpInputProvider) SetWithProbe(value string, probe types.InputLivenessProbe) error { +func (i *HttpInputProvider) SetWithProbe(_ string, value string, probe types.InputLivenessProbe) error { return nil } // SetWithExclusions adds item to input provider if it doesn't match any of the exclusions // No-op for this provider -func (i *HttpInputProvider) SetWithExclusions(value string) error { +func (i *HttpInputProvider) SetWithExclusions(_ string, value string) error { return nil } diff --git a/pkg/input/provider/interface.go b/pkg/input/provider/interface.go index e6d5da14a..1ac068514 100644 --- a/pkg/input/provider/interface.go +++ b/pkg/input/provider/interface.go @@ -59,11 +59,11 @@ type InputProvider interface { // Iterate over all inputs in order Iterate(callback func(value *contextargs.MetaInput) bool) // Set adds item to input provider - Set(value string) + Set(executionId string, value string) // SetWithProbe adds item to input provider with http probing - SetWithProbe(value string, probe types.InputLivenessProbe) error + SetWithProbe(executionId string, value string, probe types.InputLivenessProbe) error // SetWithExclusions adds item to input provider if it doesn't match any of the exclusions - SetWithExclusions(value string) error + SetWithExclusions(executionId string, value string) error // InputType returns the type of input provider InputType() string // Close the input provider and cleanup any resources diff --git a/pkg/input/provider/list/hmap.go b/pkg/input/provider/list/hmap.go index a08e909e1..0664130fa 100644 --- a/pkg/input/provider/list/hmap.go +++ b/pkg/input/provider/list/hmap.go @@ -139,7 +139,7 @@ func (i *ListInputProvider) Iterate(callback func(value *contextargs.MetaInput) } // Set normalizes and stores passed input values -func (i *ListInputProvider) Set(value string) { +func (i *ListInputProvider) Set(executionId string, value string) { URL := strings.TrimSpace(value) if URL == "" { return @@ -169,7 +169,12 @@ func (i *ListInputProvider) Set(value string) { if i.ipOptions.ScanAllIPs { // scan all ips - dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname()) + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + panic("dialers with executionId " + executionId + " not found") + } + + dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname()) if err == nil { if (len(dnsData.A) + len(dnsData.AAAA)) > 0 { var ips []string @@ -201,7 +206,12 @@ func (i *ListInputProvider) Set(value string) { ips := []string{} // only scan the target but ipv6 if it has one if i.ipOptions.IPV6 { - dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname()) + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + panic("dialers with executionId " + executionId + " not found") + } + + dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname()) if err == nil && len(dnsData.AAAA) > 0 { // pick/ prefer 1st ips = append(ips, dnsData.AAAA[0]) @@ -228,17 +238,17 @@ func (i *ListInputProvider) Set(value string) { } // SetWithProbe only sets the input if it is live -func (i *ListInputProvider) SetWithProbe(value string, probe providerTypes.InputLivenessProbe) error { +func (i *ListInputProvider) SetWithProbe(executionId string, value string, probe providerTypes.InputLivenessProbe) error { probedValue, err := probe.ProbeURL(value) if err != nil { return err } - i.Set(probedValue) + i.Set(executionId, probedValue) return nil } // SetWithExclusions normalizes and stores passed input values if not excluded -func (i *ListInputProvider) SetWithExclusions(value string) error { +func (i *ListInputProvider) SetWithExclusions(executionId string, value string) error { URL := strings.TrimSpace(value) if URL == "" { return nil @@ -247,7 +257,7 @@ func (i *ListInputProvider) SetWithExclusions(value string) error { i.skippedCount++ return nil } - i.Set(URL) + i.Set(executionId, URL) return nil } @@ -273,18 +283,20 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error { switch { case iputil.IsCIDR(target): ips := expand.CIDR(target) - i.addTargets(ips) + i.addTargets(options.ExecutionId, ips) case asn.IsASN(target): ips := expand.ASN(target) - i.addTargets(ips) + i.addTargets(options.ExecutionId, ips) default: - i.Set(target) + i.Set(options.ExecutionId, target) } } // Handle stdin if options.Stdin { - i.scanInputFromReader(readerutil.TimeoutReader{Reader: os.Stdin, Timeout: time.Duration(options.InputReadTimeout)}) + i.scanInputFromReader( + options.ExecutionId, + readerutil.TimeoutReader{Reader: os.Stdin, Timeout: time.Duration(options.InputReadTimeout)}) } // Handle target file @@ -297,7 +309,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error { } } if input != nil { - i.scanInputFromReader(input) + i.scanInputFromReader(options.ExecutionId, input) _ = input.Close() } } @@ -317,7 +329,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error { return err } for c := range ch { - i.Set(c) + i.Set(options.ExecutionId, c) } } @@ -331,7 +343,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error { ips := expand.ASN(target) i.removeTargets(ips) default: - i.Del(target) + i.Del(options.ExecutionId, target) } } } @@ -340,19 +352,19 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error { } // scanInputFromReader scans a line of input from reader and passes it for storage -func (i *ListInputProvider) scanInputFromReader(reader io.Reader) { +func (i *ListInputProvider) scanInputFromReader(executionId string, reader io.Reader) { scanner := bufio.NewScanner(reader) for scanner.Scan() { item := scanner.Text() switch { case iputil.IsCIDR(item): ips := expand.CIDR(item) - i.addTargets(ips) + i.addTargets(executionId, ips) case asn.IsASN(item): ips := expand.ASN(item) - i.addTargets(ips) + i.addTargets(executionId, ips) default: - i.Set(item) + i.Set(executionId, item) } } } @@ -371,7 +383,7 @@ func (i *ListInputProvider) isExcluded(URL string) bool { return exists } -func (i *ListInputProvider) Del(value string) { +func (i *ListInputProvider) Del(executionId string, value string) { URL := strings.TrimSpace(value) if URL == "" { return @@ -401,7 +413,12 @@ func (i *ListInputProvider) Del(value string) { if i.ipOptions.ScanAllIPs { // scan all ips - dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname()) + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + panic("dialers with executionId " + executionId + " not found") + } + + dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname()) if err == nil { if (len(dnsData.A) + len(dnsData.AAAA)) > 0 { var ips []string @@ -433,7 +450,12 @@ func (i *ListInputProvider) Del(value string) { ips := []string{} // only scan the target but ipv6 if it has one if i.ipOptions.IPV6 { - dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname()) + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + panic("dialers with executionId " + executionId + " not found") + } + + dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname()) if err == nil && len(dnsData.AAAA) > 0 { // pick/ prefer 1st ips = append(ips, dnsData.AAAA[0]) @@ -519,9 +541,9 @@ func (i *ListInputProvider) setHostMapStream(data string) { } } -func (i *ListInputProvider) addTargets(targets []string) { +func (i *ListInputProvider) addTargets(executionId string, targets []string) { for _, target := range targets { - i.Set(target) + i.Set(executionId, target) } } diff --git a/pkg/input/provider/list/hmap_test.go b/pkg/input/provider/list/hmap_test.go index cd28b247a..d2a409352 100644 --- a/pkg/input/provider/list/hmap_test.go +++ b/pkg/input/provider/list/hmap_test.go @@ -36,7 +36,7 @@ func Test_expandCIDR(t *testing.T) { input := &ListInputProvider{hostMap: hm} ips := expand.CIDR(tt.cidr) - input.addTargets(ips) + input.addTargets("", ips) // scan got := []string{} input.hostMap.Scan(func(k, _ []byte) error { @@ -137,7 +137,7 @@ func Test_scanallips_normalizeStoreInputValue(t *testing.T) { }, } - input.Set(tt.hostname) + input.Set("", tt.hostname) // scan got := []string{} input.hostMap.Scan(func(k, v []byte) error { @@ -180,7 +180,7 @@ func Test_expandASNInputValue(t *testing.T) { input := &ListInputProvider{hostMap: hm} // get the IP addresses for ASN number ips := expand.ASN(tt.asn) - input.addTargets(ips) + input.addTargets("", ips) // scan the hmap got := []string{} input.hostMap.Scan(func(k, v []byte) error { diff --git a/pkg/input/provider/simple.go b/pkg/input/provider/simple.go index c85f7871b..ac1b854df 100644 --- a/pkg/input/provider/simple.go +++ b/pkg/input/provider/simple.go @@ -19,10 +19,10 @@ func NewSimpleInputProvider() *SimpleInputProvider { } // NewSimpleInputProviderWithUrls creates a new simple input provider with the given urls -func NewSimpleInputProviderWithUrls(urls ...string) *SimpleInputProvider { +func NewSimpleInputProviderWithUrls(executionId string, urls ...string) *SimpleInputProvider { provider := NewSimpleInputProvider() for _, url := range urls { - provider.Set(url) + provider.Set(executionId, url) } return provider } @@ -42,14 +42,14 @@ func (s *SimpleInputProvider) Iterate(callback func(value *contextargs.MetaInput } // Set adds an item to the input provider -func (s *SimpleInputProvider) Set(value string) { +func (s *SimpleInputProvider) Set(_ string, value string) { metaInput := contextargs.NewMetaInput() metaInput.Input = value s.Inputs = append(s.Inputs, metaInput) } // SetWithProbe adds an item to the input provider with HTTP probing -func (s *SimpleInputProvider) SetWithProbe(value string, probe types.InputLivenessProbe) error { +func (s *SimpleInputProvider) SetWithProbe(_ string, value string, probe types.InputLivenessProbe) error { probedValue, err := probe.ProbeURL(value) if err != nil { return err @@ -61,7 +61,7 @@ func (s *SimpleInputProvider) SetWithProbe(value string, probe types.InputLivene } // SetWithExclusions adds an item to the input provider if it doesn't match any of the exclusions -func (s *SimpleInputProvider) SetWithExclusions(value string) error { +func (s *SimpleInputProvider) SetWithExclusions(_ string, value string) error { metaInput := contextargs.NewMetaInput() metaInput.Input = value s.Inputs = append(s.Inputs, metaInput) diff --git a/pkg/js/compiler/compiler.go b/pkg/js/compiler/compiler.go index cd698e4a0..3e8af5090 100644 --- a/pkg/js/compiler/compiler.go +++ b/pkg/js/compiler/compiler.go @@ -5,7 +5,7 @@ import ( "context" "fmt" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/kitabisa/go-ci" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" @@ -32,6 +32,9 @@ func New() *Compiler { // ExecuteOptions provides options for executing a script. type ExecuteOptions struct { + // ExecutionId is the id of the execution + ExecutionId string + // Callback can be used to register new runtime helper functions // ex: export etc Callback func(runtime *goja.Runtime) error diff --git a/pkg/js/compiler/init.go b/pkg/js/compiler/init.go index 92301df5e..f424f51ba 100644 --- a/pkg/js/compiler/init.go +++ b/pkg/js/compiler/init.go @@ -1,6 +1,8 @@ package compiler import ( + "sync" + "github.com/projectdiscovery/nuclei/v3/pkg/types" ) @@ -9,10 +11,13 @@ import ( var ( PoolingJsVmConcurrency = 100 NonPoolingVMConcurrency = 20 + m sync.Mutex ) // Init initializes the javascript protocol func Init(opts *types.Options) error { + m.Lock() + defer m.Unlock() if opts.JsConcurrency < 100 { // 100 is reasonable default diff --git a/pkg/js/compiler/non-pool.go b/pkg/js/compiler/non-pool.go index 74c023035..2bb87af33 100644 --- a/pkg/js/compiler/non-pool.go +++ b/pkg/js/compiler/non-pool.go @@ -3,7 +3,7 @@ package compiler import ( "sync" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" syncutil "github.com/projectdiscovery/utils/sync" ) diff --git a/pkg/js/compiler/pool.go b/pkg/js/compiler/pool.go index ac6a3dada..a8b98b012 100644 --- a/pkg/js/compiler/pool.go +++ b/pkg/js/compiler/pool.go @@ -7,9 +7,9 @@ import ( "reflect" "sync" - "github.com/dop251/goja" - "github.com/dop251/goja_nodejs/console" - "github.com/dop251/goja_nodejs/require" + "github.com/Mzack9999/goja" + "github.com/Mzack9999/goja_nodejs/console" + "github.com/Mzack9999/goja_nodejs/require" "github.com/kitabisa/go-ci" "github.com/projectdiscovery/gologger" _ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libbytes" @@ -84,6 +84,7 @@ func executeWithRuntime(runtime *goja.Runtime, p *goja.Program, args *ExecuteArg if opts != nil && opts.Cleanup != nil { opts.Cleanup(runtime) } + runtime.RemoveContextValue("executionId") }() // TODO(dwisiswant0): remove this once we get the RCA. @@ -108,8 +109,11 @@ func executeWithRuntime(runtime *goja.Runtime, p *goja.Program, args *ExecuteArg if err := opts.Callback(runtime); err != nil { return nil, err } - } + + // inject execution id and context + runtime.SetContextValue("executionId", opts.ExecutionId) + // execute the script return runtime.RunProgram(p) } diff --git a/pkg/js/devtools/bindgen/output.go b/pkg/js/devtools/bindgen/output.go index db12d24c3..42dfb0b1b 100644 --- a/pkg/js/devtools/bindgen/output.go +++ b/pkg/js/devtools/bindgen/output.go @@ -92,8 +92,8 @@ func (d *TemplateData) WriteMarkdownIndexTemplate(outputDirectory string) error return errors.Wrap(err, "could not create markdown index template") } defer func() { - _ = output.Close() - }() + _ = output.Close() + }() buffer := &bytes.Buffer{} _, _ = buffer.WriteString("# Index\n\n") diff --git a/pkg/js/devtools/bindgen/templates/go_class.tmpl b/pkg/js/devtools/bindgen/templates/go_class.tmpl index ede540471..a288b83cf 100644 --- a/pkg/js/devtools/bindgen/templates/go_class.tmpl +++ b/pkg/js/devtools/bindgen/templates/go_class.tmpl @@ -5,7 +5,7 @@ package {{.PackageName}} import ( {{$pkgName}} "{{.PackagePath}}" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libbytes/bytes.go b/pkg/js/generated/go/libbytes/bytes.go index c2955acf4..882bedc42 100644 --- a/pkg/js/generated/go/libbytes/bytes.go +++ b/pkg/js/generated/go/libbytes/bytes.go @@ -3,7 +3,7 @@ package bytes import ( lib_bytes "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/bytes" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libfs/fs.go b/pkg/js/generated/go/libfs/fs.go index bc3e50993..fd1cd76cd 100644 --- a/pkg/js/generated/go/libfs/fs.go +++ b/pkg/js/generated/go/libfs/fs.go @@ -3,7 +3,7 @@ package fs import ( lib_fs "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/fs" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libgoconsole/goconsole.go b/pkg/js/generated/go/libgoconsole/goconsole.go index c8056d505..8f218c216 100644 --- a/pkg/js/generated/go/libgoconsole/goconsole.go +++ b/pkg/js/generated/go/libgoconsole/goconsole.go @@ -3,7 +3,7 @@ package goconsole import ( lib_goconsole "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/goconsole" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libikev2/ikev2.go b/pkg/js/generated/go/libikev2/ikev2.go index 9d7e58824..453ffaa9c 100644 --- a/pkg/js/generated/go/libikev2/ikev2.go +++ b/pkg/js/generated/go/libikev2/ikev2.go @@ -3,7 +3,7 @@ package ikev2 import ( lib_ikev2 "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ikev2" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libkerberos/kerberos.go b/pkg/js/generated/go/libkerberos/kerberos.go index db367ef56..66701c2ef 100644 --- a/pkg/js/generated/go/libkerberos/kerberos.go +++ b/pkg/js/generated/go/libkerberos/kerberos.go @@ -3,7 +3,7 @@ package kerberos import ( lib_kerberos "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/kerberos" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libldap/ldap.go b/pkg/js/generated/go/libldap/ldap.go index 978ded0c0..b0c8de6f3 100644 --- a/pkg/js/generated/go/libldap/ldap.go +++ b/pkg/js/generated/go/libldap/ldap.go @@ -3,7 +3,7 @@ package ldap import ( lib_ldap "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ldap" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libmssql/mssql.go b/pkg/js/generated/go/libmssql/mssql.go index 48edb8352..252fff6bc 100644 --- a/pkg/js/generated/go/libmssql/mssql.go +++ b/pkg/js/generated/go/libmssql/mssql.go @@ -3,7 +3,7 @@ package mssql import ( lib_mssql "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/mssql" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libmysql/mysql.go b/pkg/js/generated/go/libmysql/mysql.go index 1ec181701..b4fa3723e 100644 --- a/pkg/js/generated/go/libmysql/mysql.go +++ b/pkg/js/generated/go/libmysql/mysql.go @@ -3,7 +3,7 @@ package mysql import ( lib_mysql "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/mysql" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libnet/net.go b/pkg/js/generated/go/libnet/net.go index 031bba2ba..dd9f5e8b3 100644 --- a/pkg/js/generated/go/libnet/net.go +++ b/pkg/js/generated/go/libnet/net.go @@ -3,7 +3,7 @@ package net import ( lib_net "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/net" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/liboracle/oracle.go b/pkg/js/generated/go/liboracle/oracle.go index 53c8dee1c..67110b4c8 100644 --- a/pkg/js/generated/go/liboracle/oracle.go +++ b/pkg/js/generated/go/liboracle/oracle.go @@ -3,7 +3,7 @@ package oracle import ( lib_oracle "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/oracle" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libpop3/pop3.go b/pkg/js/generated/go/libpop3/pop3.go index c84436e2f..6c51c51bf 100644 --- a/pkg/js/generated/go/libpop3/pop3.go +++ b/pkg/js/generated/go/libpop3/pop3.go @@ -3,7 +3,7 @@ package pop3 import ( lib_pop3 "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/pop3" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libpostgres/postgres.go b/pkg/js/generated/go/libpostgres/postgres.go index 0230c75b8..7d931f2be 100644 --- a/pkg/js/generated/go/libpostgres/postgres.go +++ b/pkg/js/generated/go/libpostgres/postgres.go @@ -3,7 +3,7 @@ package postgres import ( lib_postgres "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/postgres" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/librdp/rdp.go b/pkg/js/generated/go/librdp/rdp.go index f3129ef21..aee252c43 100644 --- a/pkg/js/generated/go/librdp/rdp.go +++ b/pkg/js/generated/go/librdp/rdp.go @@ -3,7 +3,7 @@ package rdp import ( lib_rdp "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/rdp" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libredis/redis.go b/pkg/js/generated/go/libredis/redis.go index a633afd84..81f997337 100644 --- a/pkg/js/generated/go/libredis/redis.go +++ b/pkg/js/generated/go/libredis/redis.go @@ -3,7 +3,7 @@ package redis import ( lib_redis "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/redis" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/librsync/rsync.go b/pkg/js/generated/go/librsync/rsync.go index a8e925d8d..6c269fcb0 100644 --- a/pkg/js/generated/go/librsync/rsync.go +++ b/pkg/js/generated/go/librsync/rsync.go @@ -3,7 +3,7 @@ package rsync import ( lib_rsync "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/rsync" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libsmb/smb.go b/pkg/js/generated/go/libsmb/smb.go index 2afe53c68..721835511 100644 --- a/pkg/js/generated/go/libsmb/smb.go +++ b/pkg/js/generated/go/libsmb/smb.go @@ -3,7 +3,7 @@ package smb import ( lib_smb "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/smb" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libsmtp/smtp.go b/pkg/js/generated/go/libsmtp/smtp.go index e27f55ac7..b17e26004 100644 --- a/pkg/js/generated/go/libsmtp/smtp.go +++ b/pkg/js/generated/go/libsmtp/smtp.go @@ -3,7 +3,7 @@ package smtp import ( lib_smtp "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/smtp" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libssh/ssh.go b/pkg/js/generated/go/libssh/ssh.go index 6a36f51eb..e71eeffe4 100644 --- a/pkg/js/generated/go/libssh/ssh.go +++ b/pkg/js/generated/go/libssh/ssh.go @@ -3,7 +3,7 @@ package ssh import ( lib_ssh "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ssh" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libstructs/structs.go b/pkg/js/generated/go/libstructs/structs.go index e17e629dd..a817bb335 100644 --- a/pkg/js/generated/go/libstructs/structs.go +++ b/pkg/js/generated/go/libstructs/structs.go @@ -3,7 +3,7 @@ package structs import ( lib_structs "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libtelnet/telnet.go b/pkg/js/generated/go/libtelnet/telnet.go index 82a08c253..a9b50a5fb 100644 --- a/pkg/js/generated/go/libtelnet/telnet.go +++ b/pkg/js/generated/go/libtelnet/telnet.go @@ -3,7 +3,7 @@ package telnet import ( lib_telnet "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/telnet" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/generated/go/libvnc/vnc.go b/pkg/js/generated/go/libvnc/vnc.go index affc3c933..625f3776d 100644 --- a/pkg/js/generated/go/libvnc/vnc.go +++ b/pkg/js/generated/go/libvnc/vnc.go @@ -3,7 +3,7 @@ package vnc import ( lib_vnc "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/vnc" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/global/helpers.go b/pkg/js/global/helpers.go index 5510d7ae3..3df194d37 100644 --- a/pkg/js/global/helpers.go +++ b/pkg/js/global/helpers.go @@ -3,7 +3,7 @@ package global import ( "encoding/base64" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" ) diff --git a/pkg/js/global/scripts.go b/pkg/js/global/scripts.go index 2c1d56e12..6101eaf42 100644 --- a/pkg/js/global/scripts.go +++ b/pkg/js/global/scripts.go @@ -9,7 +9,7 @@ import ( "reflect" "time" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/logrusorgru/aurora" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" @@ -113,8 +113,7 @@ func initBuiltInFunc(runtime *goja.Runtime) { "isPortOpen(host string, port string, [timeout int]) bool", }, Description: "isPortOpen checks if given TCP port is open on host. timeout is optional and defaults to 5 seconds", - FuncDecl: func(host string, port string, timeout ...int) (bool, error) { - ctx := context.Background() + FuncDecl: func(ctx context.Context, host string, port string, timeout ...int) (bool, error) { if len(timeout) > 0 { var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout[0])*time.Second) @@ -123,7 +122,14 @@ func initBuiltInFunc(runtime *goja.Runtime) { if host == "" || port == "" { return false, errkit.New("isPortOpen: host or port is empty") } - conn, err := protocolstate.Dialer.Dial(ctx, "tcp", net.JoinHostPort(host, port)) + + executionId := ctx.Value("executionId").(string) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + panic("dialers with executionId " + executionId + " not found") + } + + conn, err := dialer.Fastdialer.Dial(ctx, "tcp", net.JoinHostPort(host, port)) if err != nil { return false, err } @@ -138,8 +144,7 @@ func initBuiltInFunc(runtime *goja.Runtime) { "isUDPPortOpen(host string, port string, [timeout int]) bool", }, Description: "isUDPPortOpen checks if the given UDP port is open on the host. Timeout is optional and defaults to 5 seconds.", - FuncDecl: func(host string, port string, timeout ...int) (bool, error) { - ctx := context.Background() + FuncDecl: func(ctx context.Context, host string, port string, timeout ...int) (bool, error) { if len(timeout) > 0 { var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout[0])*time.Second) @@ -148,7 +153,14 @@ func initBuiltInFunc(runtime *goja.Runtime) { if host == "" || port == "" { return false, errkit.New("isPortOpen: host or port is empty") } - conn, err := protocolstate.Dialer.Dial(ctx, "udp", net.JoinHostPort(host, port)) + + executionId := ctx.Value("executionId").(string) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + panic("dialers with executionId " + executionId + " not found") + } + + conn, err := dialer.Fastdialer.Dial(ctx, "udp", net.JoinHostPort(host, port)) if err != nil { return false, err } diff --git a/pkg/js/global/scripts_test.go b/pkg/js/global/scripts_test.go index 4105695f6..1b721da63 100644 --- a/pkg/js/global/scripts_test.go +++ b/pkg/js/global/scripts_test.go @@ -3,9 +3,9 @@ package global import ( "testing" - "github.com/dop251/goja" - "github.com/dop251/goja_nodejs/console" - "github.com/dop251/goja_nodejs/require" + "github.com/Mzack9999/goja" + "github.com/Mzack9999/goja_nodejs/console" + "github.com/Mzack9999/goja_nodejs/require" ) func TestScriptsRuntime(t *testing.T) { diff --git a/pkg/js/gojs/gojs.go b/pkg/js/gojs/gojs.go index 3b43fe13f..5d4af6e87 100644 --- a/pkg/js/gojs/gojs.go +++ b/pkg/js/gojs/gojs.go @@ -1,10 +1,12 @@ package gojs import ( + "context" + "reflect" "sync" - "github.com/dop251/goja" - "github.com/dop251/goja_nodejs/require" + "github.com/Mzack9999/goja" + "github.com/Mzack9999/goja_nodejs/require" "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" ) @@ -47,17 +49,67 @@ func (p *GojaModule) Name() string { return p.name } -func (p *GojaModule) Set(objects Objects) Module { +// wrapModuleFunc wraps a Go function with context injection for modules +// nolint +func wrapModuleFunc(runtime *goja.Runtime, fn interface{}) interface{} { + fnType := reflect.TypeOf(fn) + if fnType.Kind() != reflect.Func { + return fn + } + // Only wrap if first parameter is context.Context + if fnType.NumIn() == 0 || fnType.In(0) != reflect.TypeOf((*context.Context)(nil)).Elem() { + return fn // Return original function unchanged if it doesn't have context.Context as first arg + } + + // Create input and output type slices + inTypes := make([]reflect.Type, fnType.NumIn()) + for i := 0; i < fnType.NumIn(); i++ { + inTypes[i] = fnType.In(i) + } + outTypes := make([]reflect.Type, fnType.NumOut()) + for i := 0; i < fnType.NumOut(); i++ { + outTypes[i] = fnType.Out(i) + } + + // Create a new function with same signature + newFnType := reflect.FuncOf(inTypes, outTypes, fnType.IsVariadic()) + newFn := reflect.MakeFunc(newFnType, func(args []reflect.Value) []reflect.Value { + // Get context from runtime + var ctx context.Context + if ctxVal := runtime.Get("context"); ctxVal != nil { + if ctxObj, ok := ctxVal.Export().(context.Context); ok { + ctx = ctxObj + } + } + if ctx == nil { + ctx = context.Background() + } + + // Add execution ID to context if available + if execID := runtime.Get("executionId"); execID != nil { + //nolint + ctx = context.WithValue(ctx, "executionId", execID.String()) + } + + // Replace first argument (context) with our context + args[0] = reflect.ValueOf(ctx) + + // Call original function with modified arguments + return reflect.ValueOf(fn).Call(args) + }) + + return newFn.Interface() +} + +func (p *GojaModule) Set(objects Objects) Module { for k, v := range objects { p.sets[k] = v } - return p } func (p *GojaModule) Require(runtime *goja.Runtime, module *goja.Object) { - o := module.Get("exports").(*goja.Object) for k, v := range p.sets { diff --git a/pkg/js/gojs/set.go b/pkg/js/gojs/set.go index 9703a3c6e..6aff9f1c7 100644 --- a/pkg/js/gojs/set.go +++ b/pkg/js/gojs/set.go @@ -1,7 +1,10 @@ package gojs import ( - "github.com/dop251/goja" + "context" + "reflect" + + "github.com/Mzack9999/goja" errorutil "github.com/projectdiscovery/utils/errors" ) @@ -22,6 +25,58 @@ func (f *FuncOpts) valid() bool { return f.Name != "" && f.FuncDecl != nil && len(f.Signatures) > 0 && f.Description != "" } +// wrapWithContext wraps a Go function with context injection +// nolint +func wrapWithContext(runtime *goja.Runtime, fn interface{}) interface{} { + fnType := reflect.TypeOf(fn) + if fnType.Kind() != reflect.Func { + return fn + } + + // Only wrap if first parameter is context.Context + if fnType.NumIn() == 0 || fnType.In(0) != reflect.TypeOf((*context.Context)(nil)).Elem() { + return fn // Return original function unchanged if it doesn't have context.Context as first arg + } + + // Create input and output type slices + inTypes := make([]reflect.Type, fnType.NumIn()) + for i := 0; i < fnType.NumIn(); i++ { + inTypes[i] = fnType.In(i) + } + outTypes := make([]reflect.Type, fnType.NumOut()) + for i := 0; i < fnType.NumOut(); i++ { + outTypes[i] = fnType.Out(i) + } + + // Create a new function with same signature + newFnType := reflect.FuncOf(inTypes, outTypes, fnType.IsVariadic()) + newFn := reflect.MakeFunc(newFnType, func(args []reflect.Value) []reflect.Value { + // Get context from runtime + var ctx context.Context + if ctxVal := runtime.Get("context"); ctxVal != nil { + if ctxObj, ok := ctxVal.Export().(context.Context); ok { + ctx = ctxObj + } + } + if ctx == nil { + ctx = context.Background() + } + + // Add execution ID to context if available + if execID := runtime.Get("executionId"); execID != nil { + ctx = context.WithValue(ctx, "executionId", execID.String()) + } + + // Replace first argument (context) with our context + args[0] = reflect.ValueOf(ctx) + + // Call original function with modified arguments + return reflect.ValueOf(fn).Call(args) + }) + + return newFn.Interface() +} + // RegisterFunc registers a function with given name, signatures and description func RegisterFuncWithSignature(runtime *goja.Runtime, opts FuncOpts) error { if runtime == nil { @@ -30,5 +85,8 @@ func RegisterFuncWithSignature(runtime *goja.Runtime, opts FuncOpts) error { if !opts.valid() { return ErrInvalidFuncOpts.Msgf("name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description) } - return runtime.Set(opts.Name, opts.FuncDecl) + + // Wrap the function with context injection + // wrappedFn := wrapWithContext(runtime, opts.FuncDecl) + return runtime.Set(opts.Name, opts.FuncDecl /* wrappedFn */) } diff --git a/pkg/js/libs/bytes/buffer.go b/pkg/js/libs/bytes/buffer.go index e38474182..87a5f5cd1 100644 --- a/pkg/js/libs/bytes/buffer.go +++ b/pkg/js/libs/bytes/buffer.go @@ -3,7 +3,7 @@ package bytes import ( "encoding/hex" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs" "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" ) diff --git a/pkg/js/libs/goconsole/log.go b/pkg/js/libs/goconsole/log.go index 994d6609a..e5b16f8d7 100644 --- a/pkg/js/libs/goconsole/log.go +++ b/pkg/js/libs/goconsole/log.go @@ -1,7 +1,7 @@ package goconsole import ( - "github.com/dop251/goja_nodejs/console" + "github.com/Mzack9999/goja_nodejs/console" "github.com/projectdiscovery/gologger" ) diff --git a/pkg/js/libs/kerberos/kerberosx.go b/pkg/js/libs/kerberos/kerberosx.go index ea3e5921d..c049f1024 100644 --- a/pkg/js/libs/kerberos/kerberosx.go +++ b/pkg/js/libs/kerberos/kerberosx.go @@ -3,7 +3,7 @@ package kerberos import ( "strings" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" kclient "github.com/jcmturner/gokrb5/v8/client" kconfig "github.com/jcmturner/gokrb5/v8/config" "github.com/jcmturner/gokrb5/v8/iana/errorcode" @@ -109,7 +109,8 @@ func NewKerberosClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.O if controller != "" { // validate controller hostport - if !protocolstate.IsHostAllowed(controller) { + executionId := c.nj.ExecutionId() + if !protocolstate.IsHostAllowed(executionId, controller) { c.nj.Throw("domain controller address blacklisted by network policy") } @@ -246,16 +247,18 @@ func (c *Client) GetServiceTicket(User, Pass, SPN string) (TGS, error) { c.nj.Require(Pass != "", "Pass cannot be empty") c.nj.Require(SPN != "", "SPN cannot be empty") + executionId := c.nj.ExecutionId() + if len(c.Krb5Config.Realms) > 0 { // this means dc address was given for _, r := range c.Krb5Config.Realms { for _, kdc := range r.KDC { - if !protocolstate.IsHostAllowed(kdc) { + if !protocolstate.IsHostAllowed(executionId, kdc) { c.nj.Throw("KDC address %v blacklisted by network policy", kdc) } } for _, kpasswd := range r.KPasswdServer { - if !protocolstate.IsHostAllowed(kpasswd) { + if !protocolstate.IsHostAllowed(executionId, kpasswd) { c.nj.Throw("Kpasswd address %v blacklisted by network policy", kpasswd) } } @@ -265,7 +268,7 @@ func (c *Client) GetServiceTicket(User, Pass, SPN string) (TGS, error) { // and check if they are allowed by network policy _, kdcs, _ := c.Krb5Config.GetKDCs(c.Realm, true) for _, v := range kdcs { - if !protocolstate.IsHostAllowed(v) { + if !protocolstate.IsHostAllowed(executionId, v) { c.nj.Throw("KDC address %v blacklisted by network policy", v) } } diff --git a/pkg/js/libs/kerberos/sendtokdc.go b/pkg/js/libs/kerberos/sendtokdc.go index 0cb3f47e1..a065f496b 100644 --- a/pkg/js/libs/kerberos/sendtokdc.go +++ b/pkg/js/libs/kerberos/sendtokdc.go @@ -68,6 +68,12 @@ func sendToKDCTcp(kclient *Client, msg string) ([]byte, error) { kclient.nj.HandleError(err, "error getting KDCs") kclient.nj.Require(len(kdcs) > 0, "no KDCs found") + executionId := kclient.nj.ExecutionId() + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } + var errs []string for i := 1; i <= len(kdcs); i++ { host, port, err := net.SplitHostPort(kdcs[i]) @@ -75,14 +81,14 @@ func sendToKDCTcp(kclient *Client, msg string) ([]byte, error) { // use that ip address instead of realm/domain for resolving host = kclient.config.ip } - tcpConn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port)) + tcpConn, err := dialers.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port)) if err != nil { errs = append(errs, fmt.Sprintf("error establishing connection to %s: %v", kdcs[i], err)) continue } defer func() { - _ = tcpConn.Close() - }() + _ = tcpConn.Close() + }() _ = tcpConn.SetDeadline(time.Now().Add(time.Duration(kclient.config.timeout) * time.Second)) //read and write deadline rb, err := sendTCP(tcpConn.(*net.TCPConn), []byte(msg)) if err != nil { @@ -103,6 +109,11 @@ func sendToKDCUdp(kclient *Client, msg string) ([]byte, error) { kclient.nj.HandleError(err, "error getting KDCs") kclient.nj.Require(len(kdcs) > 0, "no KDCs found") + executionId := kclient.nj.ExecutionId() + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } var errs []string for i := 1; i <= len(kdcs); i++ { host, port, err := net.SplitHostPort(kdcs[i]) @@ -110,14 +121,14 @@ func sendToKDCUdp(kclient *Client, msg string) ([]byte, error) { // use that ip address instead of realm/domain for resolving host = kclient.config.ip } - udpConn, err := protocolstate.Dialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port)) + udpConn, err := dialers.Fastdialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port)) if err != nil { errs = append(errs, fmt.Sprintf("error establishing connection to %s: %v", kdcs[i], err)) continue } defer func() { - _ = udpConn.Close() - }() + _ = udpConn.Close() + }() _ = udpConn.SetDeadline(time.Now().Add(time.Duration(kclient.config.timeout) * time.Second)) //read and write deadline rb, err := sendUDP(udpConn.(*net.UDPConn), []byte(msg)) if err != nil { @@ -137,8 +148,8 @@ func sendToKDCUdp(kclient *Client, msg string) ([]byte, error) { func sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) { var r []byte defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() _, err := conn.Write(b) if err != nil { return r, fmt.Errorf("error sending to (%s): %v", conn.RemoteAddr().String(), err) @@ -158,8 +169,8 @@ func sendUDP(conn *net.UDPConn, b []byte) ([]byte, error) { // sendTCP sends bytes to connection over TCP. func sendTCP(conn *net.TCPConn, b []byte) ([]byte, error) { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() var r []byte // RFC 4120 7.2.2 specifies the first 4 bytes indicate the length of the message in big endian order. hb := make([]byte, 4) diff --git a/pkg/js/libs/ldap/ldap.go b/pkg/js/libs/ldap/ldap.go index 8e9e4eec5..d5e6f3512 100644 --- a/pkg/js/libs/ldap/ldap.go +++ b/pkg/js/libs/ldap/ldap.go @@ -8,7 +8,7 @@ import ( "net/url" "strings" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/go-ldap/ldap/v3" "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" @@ -86,12 +86,18 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object { u, err := url.Parse(ldapUrl) c.nj.HandleError(err, "invalid ldap url supported schemas are ldap://, ldaps://, ldapi://, and cldap://") + executionId := c.nj.ExecutionId() + dialers := protocolstate.GetDialersWithId(executionId) + if dialers == nil { + panic("dialers with executionId " + executionId + " not found") + } + var conn net.Conn if u.Scheme == "ldapi" { if u.Path == "" || u.Path == "/" { u.Path = "/var/run/slapd/ldapi" } - conn, err = protocolstate.Dialer.Dial(context.TODO(), "unix", u.Path) + conn, err = dialers.Fastdialer.Dial(context.TODO(), "unix", u.Path) c.nj.HandleError(err, "failed to connect to ldap server") } else { host, port, err := net.SplitHostPort(u.Host) @@ -110,12 +116,12 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object { if port == "" { port = ldap.DefaultLdapPort } - conn, err = protocolstate.Dialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port)) + conn, err = dialers.Fastdialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port)) case "ldap": if port == "" { port = ldap.DefaultLdapPort } - conn, err = protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port)) + conn, err = dialers.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port)) case "ldaps": if port == "" { port = ldap.DefaultLdapsPort @@ -124,7 +130,7 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object { if c.cfg.ServerName != "" { serverName = c.cfg.ServerName } - conn, err = protocolstate.Dialer.DialTLSWithConfig(context.TODO(), "tcp", net.JoinHostPort(host, port), + conn, err = dialers.Fastdialer.DialTLSWithConfig(context.TODO(), "tcp", net.JoinHostPort(host, port), &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS10, ServerName: serverName}) default: err = fmt.Errorf("unsupported ldap url schema %v", u.Scheme) diff --git a/pkg/js/libs/mssql/memo.mssql.go b/pkg/js/libs/mssql/memo.mssql.go index e57dec5cd..a8af1a6af 100755 --- a/pkg/js/libs/mssql/memo.mssql.go +++ b/pkg/js/libs/mssql/memo.mssql.go @@ -10,11 +10,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedconnect(host string, port int, username string, password string, dbName string) (bool, error) { +func memoizedconnect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) { hash := "connect" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return connect(host, port, username, password, dbName) + return connect(executionId, host, port, username, password, dbName) }) if err != nil { return false, err @@ -26,11 +26,11 @@ func memoizedconnect(host string, port int, username string, password string, db return false, errors.New("could not convert cached result") } -func memoizedisMssql(host string, port int) (bool, error) { +func memoizedisMssql(executionId string, host string, port int) (bool, error) { hash := "isMssql" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isMssql(host, port) + return isMssql(executionId, host, port) }) if err != nil { return false, err diff --git a/pkg/js/libs/mssql/mssql.go b/pkg/js/libs/mssql/mssql.go index 2e986e946..4f9caf275 100644 --- a/pkg/js/libs/mssql/mssql.go +++ b/pkg/js/libs/mssql/mssql.go @@ -36,8 +36,9 @@ type ( // const client = new mssql.MSSQLClient; // const connected = client.Connect('acme.com', 1433, 'username', 'password'); // ``` -func (c *MSSQLClient) Connect(host string, port int, username, password string) (bool, error) { - return memoizedconnect(host, port, username, password, "master") +func (c *MSSQLClient) Connect(ctx context.Context, host string, port int, username, password string) (bool, error) { + executionId := ctx.Value("executionId").(string) + return memoizedconnect(executionId, host, port, username, password, "master") } // ConnectWithDB connects to MS SQL database using given credentials and database name. @@ -50,16 +51,17 @@ func (c *MSSQLClient) Connect(host string, port int, username, password string) // const client = new mssql.MSSQLClient; // const connected = client.ConnectWithDB('acme.com', 1433, 'username', 'password', 'master'); // ``` -func (c *MSSQLClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) { - return memoizedconnect(host, port, username, password, dbName) +func (c *MSSQLClient) ConnectWithDB(ctx context.Context, host string, port int, username, password, dbName string) (bool, error) { + executionId := ctx.Value("executionId").(string) + return memoizedconnect(executionId, host, port, username, password, dbName) } // @memo -func connect(host string, port int, username string, password string, dbName string) (bool, error) { +func connect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) { if host == "" || port <= 0 { return false, fmt.Errorf("invalid host or port") } - if !protocolstate.IsHostAllowed(host) { + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return false, protocolstate.ErrHostDenied.Msgf(host) } @@ -77,8 +79,8 @@ func connect(host string, port int, username string, password string, dbName str return false, err } defer func() { - _ = db.Close() - }() + _ = db.Close() + }() _, err = db.Exec("select 1") if err != nil { @@ -107,24 +109,30 @@ func connect(host string, port int, username string, password string, dbName str // const mssql = require('nuclei/mssql'); // const isMssql = mssql.IsMssql('acme.com', 1433); // ``` -func (c *MSSQLClient) IsMssql(host string, port int) (bool, error) { - return memoizedisMssql(host, port) +func (c *MSSQLClient) IsMssql(ctx context.Context, host string, port int) (bool, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisMssql(executionId, host, port) } // @memo -func isMssql(host string, port int) (bool, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) if err != nil { return false, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() data, check, err := mssql.DetectMSSQL(conn, 5*time.Second) if check && err != nil { @@ -147,18 +155,19 @@ func isMssql(host string, port int) (bool, error) { // const result = client.ExecuteQuery('acme.com', 1433, 'username', 'password', 'master', 'SELECT @@version'); // log(to_json(result)); // ``` -func (c *MSSQLClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) { +func (c *MSSQLClient) ExecuteQuery(ctx context.Context, host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) { + executionId := ctx.Value("executionId").(string) if host == "" || port <= 0 { return nil, fmt.Errorf("invalid host or port") } - if !protocolstate.IsHostAllowed(host) { + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return nil, protocolstate.ErrHostDenied.Msgf(host) } target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) - ok, err := c.IsMssql(host, port) + ok, err := c.IsMssql(ctx, host, port) if err != nil { return nil, err } @@ -177,8 +186,8 @@ func (c *MSSQLClient) ExecuteQuery(host string, port int, username, password, db return nil, err } defer func() { - _ = db.Close() - }() + _ = db.Close() + }() db.SetMaxOpenConns(1) db.SetMaxIdleConns(0) diff --git a/pkg/js/libs/mysql/memo.mysql.go b/pkg/js/libs/mysql/memo.mysql.go index 60fda434c..a2c1d2d09 100755 --- a/pkg/js/libs/mysql/memo.mysql.go +++ b/pkg/js/libs/mysql/memo.mysql.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisMySQL(host string, port int) (bool, error) { +func memoizedisMySQL(executionId string, host string, port int) (bool, error) { hash := "isMySQL" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isMySQL(host, port) + return isMySQL(executionId, host, port) }) if err != nil { return false, err @@ -24,11 +24,11 @@ func memoizedisMySQL(host string, port int) (bool, error) { return false, errors.New("could not convert cached result") } -func memoizedfingerprintMySQL(host string, port int) (MySQLInfo, error) { +func memoizedfingerprintMySQL(executionId string, host string, port int) (MySQLInfo, error) { hash := "fingerprintMySQL" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return fingerprintMySQL(host, port) + return fingerprintMySQL(executionId, host, port) }) if err != nil { return MySQLInfo{}, err diff --git a/pkg/js/libs/mysql/mysql.go b/pkg/js/libs/mysql/mysql.go index 214a76901..c48c73a83 100644 --- a/pkg/js/libs/mysql/mysql.go +++ b/pkg/js/libs/mysql/mysql.go @@ -35,24 +35,30 @@ type ( // const mysql = require('nuclei/mysql'); // const isMySQL = mysql.IsMySQL('acme.com', 3306); // ``` -func (c *MySQLClient) IsMySQL(host string, port int) (bool, error) { +func (c *MySQLClient) IsMySQL(ctx context.Context, host string, port int) (bool, error) { + executionId := ctx.Value("executionId").(string) // todo: why this is exposed? Service fingerprint should be automatic - return memoizedisMySQL(host, port) + return memoizedisMySQL(executionId, host, port) } // @memo -func isMySQL(host string, port int) (bool, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) if err != nil { return false, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() plugin := &mysqlplugin.MYSQLPlugin{} service, err := plugin.Run(conn, 5*time.Second, plugins.Target{Host: host}) @@ -75,14 +81,15 @@ func isMySQL(host string, port int) (bool, error) { // const client = new mysql.MySQLClient; // const connected = client.Connect('acme.com', 3306, 'username', 'password'); // ``` -func (c *MySQLClient) Connect(host string, port int, username, password string) (bool, error) { - if !protocolstate.IsHostAllowed(host) { +func (c *MySQLClient) Connect(ctx context.Context, host string, port int, username, password string) (bool, error) { + executionId := ctx.Value("executionId").(string) + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return false, protocolstate.ErrHostDenied.Msgf(host) } // executing queries implies the remote mysql service - ok, err := c.IsMySQL(host, port) + ok, err := c.IsMySQL(ctx, host, port) if err != nil { return false, err } @@ -127,24 +134,30 @@ type ( // const info = mysql.FingerprintMySQL('acme.com', 3306); // log(to_json(info)); // ``` -func (c *MySQLClient) FingerprintMySQL(host string, port int) (MySQLInfo, error) { - return memoizedfingerprintMySQL(host, port) +func (c *MySQLClient) FingerprintMySQL(ctx context.Context, host string, port int) (MySQLInfo, error) { + executionId := ctx.Value("executionId").(string) + return memoizedfingerprintMySQL(executionId, host, port) } // @memo -func fingerprintMySQL(host string, port int) (MySQLInfo, error) { +func fingerprintMySQL(executionId string, host string, port int) (MySQLInfo, error) { info := MySQLInfo{} - if !protocolstate.IsHostAllowed(host) { + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return info, protocolstate.ErrHostDenied.Msgf(host) } - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return MySQLInfo{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) if err != nil { return info, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() plugin := &mysqlplugin.MYSQLPlugin{} service, err := plugin.Run(conn, 5*time.Second, plugins.Target{Host: host}) @@ -192,14 +205,15 @@ func (c *MySQLClient) ConnectWithDSN(dsn string) (bool, error) { // const result = mysql.ExecuteQueryWithOpts(options, 'SELECT * FROM users'); // log(to_json(result)); // ``` -func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*utils.SQLResult, error) { - if !protocolstate.IsHostAllowed(opts.Host) { +func (c *MySQLClient) ExecuteQueryWithOpts(ctx context.Context, opts MySQLOptions, query string) (*utils.SQLResult, error) { + executionId := ctx.Value("executionId").(string) + if !protocolstate.IsHostAllowed(executionId, opts.Host) { // host is not valid according to network policy return nil, protocolstate.ErrHostDenied.Msgf(opts.Host) } // executing queries implies the remote mysql service - ok, err := c.IsMySQL(opts.Host, opts.Port) + ok, err := c.IsMySQL(ctx, opts.Host, opts.Port) if err != nil { return nil, err } @@ -217,8 +231,8 @@ func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*ut return nil, err } defer func() { - _ = db.Close() - }() + _ = db.Close() + }() db.SetMaxOpenConns(1) db.SetMaxIdleConns(0) @@ -246,9 +260,9 @@ func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*ut // const result = mysql.ExecuteQuery('acme.com', 3306, 'username', 'password', 'SELECT * FROM users'); // log(to_json(result)); // ``` -func (c *MySQLClient) ExecuteQuery(host string, port int, username, password, query string) (*utils.SQLResult, error) { +func (c *MySQLClient) ExecuteQuery(ctx context.Context, host string, port int, username, password, query string) (*utils.SQLResult, error) { // executing queries implies the remote mysql service - ok, err := c.IsMySQL(host, port) + ok, err := c.IsMySQL(ctx, host, port) if err != nil { return nil, err } @@ -256,7 +270,7 @@ func (c *MySQLClient) ExecuteQuery(host string, port int, username, password, qu return nil, fmt.Errorf("not a mysql service") } - return c.ExecuteQueryWithOpts(MySQLOptions{ + return c.ExecuteQueryWithOpts(ctx, MySQLOptions{ Host: host, Port: port, Protocol: "tcp", @@ -273,8 +287,8 @@ func (c *MySQLClient) ExecuteQuery(host string, port int, username, password, qu // const result = mysql.ExecuteQueryOnDB('acme.com', 3306, 'username', 'password', 'dbname', 'SELECT * FROM users'); // log(to_json(result)); // ``` -func (c *MySQLClient) ExecuteQueryOnDB(host string, port int, username, password, dbname, query string) (*utils.SQLResult, error) { - return c.ExecuteQueryWithOpts(MySQLOptions{ +func (c *MySQLClient) ExecuteQueryOnDB(ctx context.Context, host string, port int, username, password, dbname, query string) (*utils.SQLResult, error) { + return c.ExecuteQueryWithOpts(ctx, MySQLOptions{ Host: host, Port: port, Protocol: "tcp", diff --git a/pkg/js/libs/mysql/mysql_private.go b/pkg/js/libs/mysql/mysql_private.go index 7a5edebc1..c731efd93 100644 --- a/pkg/js/libs/mysql/mysql_private.go +++ b/pkg/js/libs/mysql/mysql_private.go @@ -78,8 +78,8 @@ func connectWithDSN(dsn string) (bool, error) { return false, err } defer func() { - _ = db.Close() - }() + _ = db.Close() + }() db.SetMaxOpenConns(1) db.SetMaxIdleConns(0) diff --git a/pkg/js/libs/net/net.go b/pkg/js/libs/net/net.go index f1237f0eb..1db091636 100644 --- a/pkg/js/libs/net/net.go +++ b/pkg/js/libs/net/net.go @@ -25,8 +25,13 @@ var ( // const net = require('nuclei/net'); // const conn = net.Open('tcp', 'acme.com:80'); // ``` -func Open(protocol, address string) (*NetConn, error) { - conn, err := protocolstate.Dialer.Dial(context.TODO(), protocol, address) +func Open(ctx context.Context, protocol, address string) (*NetConn, error) { + executionId := ctx.Value("executionId").(string) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } + conn, err := dialer.Fastdialer.Dial(ctx, protocol, address) if err != nil { return nil, err } @@ -40,7 +45,7 @@ func Open(protocol, address string) (*NetConn, error) { // const net = require('nuclei/net'); // const conn = net.OpenTLS('tcp', 'acme.com:443'); // ``` -func OpenTLS(protocol, address string) (*NetConn, error) { +func OpenTLS(ctx context.Context, protocol, address string) (*NetConn, error) { config := &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS10} host, _, _ := net.SplitHostPort(address) if host != "" { @@ -48,7 +53,13 @@ func OpenTLS(protocol, address string) (*NetConn, error) { c.ServerName = host config = c } - conn, err := protocolstate.Dialer.DialTLSWithConfig(context.TODO(), protocol, address, config) + executionId := ctx.Value("executionId").(string) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.DialTLSWithConfig(ctx, protocol, address, config) if err != nil { return nil, err } diff --git a/pkg/js/libs/oracle/memo.oracle.go b/pkg/js/libs/oracle/memo.oracle.go index 451f2f642..20931f280 100755 --- a/pkg/js/libs/oracle/memo.oracle.go +++ b/pkg/js/libs/oracle/memo.oracle.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisOracle(host string, port int) (IsOracleResponse, error) { +func memoizedisOracle(executionId string, host string, port int) (IsOracleResponse, error) { hash := "isOracle" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isOracle(host, port) + return isOracle(executionId, host, port) }) if err != nil { return IsOracleResponse{}, err diff --git a/pkg/js/libs/oracle/oracle.go b/pkg/js/libs/oracle/oracle.go index ed8193fd9..9d4117d85 100644 --- a/pkg/js/libs/oracle/oracle.go +++ b/pkg/js/libs/oracle/oracle.go @@ -2,6 +2,7 @@ package oracle import ( "context" + "fmt" "net" "strconv" "time" @@ -32,16 +33,22 @@ type ( // const isOracle = oracle.IsOracle('acme.com', 1521); // log(toJSON(isOracle)); // ``` -func IsOracle(host string, port int) (IsOracleResponse, error) { - return memoizedisOracle(host, port) +func IsOracle(ctx context.Context, host string, port int) (IsOracleResponse, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisOracle(executionId, host, port) } // @memo -func isOracle(host string, port int) (IsOracleResponse, error) { +func isOracle(executionId string, host string, port int) (IsOracleResponse, error) { resp := IsOracleResponse{} + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return IsOracleResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) if err != nil { return resp, err } diff --git a/pkg/js/libs/pop3/memo.pop3.go b/pkg/js/libs/pop3/memo.pop3.go index dbd5e4632..61ef1dcd0 100755 --- a/pkg/js/libs/pop3/memo.pop3.go +++ b/pkg/js/libs/pop3/memo.pop3.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisPoP3(host string, port int) (IsPOP3Response, error) { +func memoizedisPoP3(executionId string, host string, port int) (IsPOP3Response, error) { hash := "isPoP3" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isPoP3(host, port) + return isPoP3(executionId, host, port) }) if err != nil { return IsPOP3Response{}, err diff --git a/pkg/js/libs/pop3/pop3.go b/pkg/js/libs/pop3/pop3.go index 5b236a612..c9d5ce175 100644 --- a/pkg/js/libs/pop3/pop3.go +++ b/pkg/js/libs/pop3/pop3.go @@ -2,6 +2,7 @@ package pop3 import ( "context" + "fmt" "net" "strconv" "time" @@ -33,16 +34,22 @@ type ( // const isPOP3 = pop3.IsPOP3('acme.com', 110); // log(toJSON(isPOP3)); // ``` -func IsPOP3(host string, port int) (IsPOP3Response, error) { - return memoizedisPoP3(host, port) +func IsPOP3(ctx context.Context, host string, port int) (IsPOP3Response, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisPoP3(executionId, host, port) } // @memo -func isPoP3(host string, port int) (IsPOP3Response, error) { +func isPoP3(executionId string, host string, port int) (IsPOP3Response, error) { resp := IsPOP3Response{} + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return IsPOP3Response{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) if err != nil { return resp, err } diff --git a/pkg/js/libs/postgres/memo.postgres.go b/pkg/js/libs/postgres/memo.postgres.go index 9c61356b0..4cee2ddd5 100755 --- a/pkg/js/libs/postgres/memo.postgres.go +++ b/pkg/js/libs/postgres/memo.postgres.go @@ -12,11 +12,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisPostgres(host string, port int) (bool, error) { +func memoizedisPostgres(executionId string, host string, port int) (bool, error) { hash := "isPostgres" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isPostgres(host, port) + return isPostgres(executionId, host, port) }) if err != nil { return false, err @@ -28,11 +28,11 @@ func memoizedisPostgres(host string, port int) (bool, error) { return false, errors.New("could not convert cached result") } -func memoizedexecuteQuery(host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) { +func memoizedexecuteQuery(executionId string, host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) { hash := "executeQuery" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName) + ":" + fmt.Sprint(query) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return executeQuery(host, port, username, password, dbName, query) + return executeQuery(executionId, host, port, username, password, dbName, query) }) if err != nil { return nil, err @@ -44,11 +44,11 @@ func memoizedexecuteQuery(host string, port int, username string, password strin return nil, errors.New("could not convert cached result") } -func memoizedconnect(host string, port int, username string, password string, dbName string) (bool, error) { +func memoizedconnect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) { hash := "connect" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return connect(host, port, username, password, dbName) + return connect(executionId, host, port, username, password, dbName) }) if err != nil { return false, err diff --git a/pkg/js/libs/postgres/postgres.go b/pkg/js/libs/postgres/postgres.go index d8b76e8e5..322048a8b 100644 --- a/pkg/js/libs/postgres/postgres.go +++ b/pkg/js/libs/postgres/postgres.go @@ -36,22 +36,28 @@ type ( // const postgres = require('nuclei/postgres'); // const isPostgres = postgres.IsPostgres('acme.com', 5432); // ``` -func (c *PGClient) IsPostgres(host string, port int) (bool, error) { +func (c *PGClient) IsPostgres(ctx context.Context, host string, port int) (bool, error) { + executionId := ctx.Value("executionId").(string) // todo: why this is exposed? Service fingerprint should be automatic - return memoizedisPostgres(host, port) + return memoizedisPostgres(executionId, host, port) } // @memo -func isPostgres(host string, port int) (bool, error) { +func isPostgres(executionId string, host string, port int) (bool, error) { timeout := 10 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return false, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() _ = conn.SetDeadline(time.Now().Add(timeout)) @@ -76,15 +82,16 @@ func isPostgres(host string, port int) (bool, error) { // const client = new postgres.PGClient; // const connected = client.Connect('acme.com', 5432, 'username', 'password'); // ``` -func (c *PGClient) Connect(host string, port int, username, password string) (bool, error) { - ok, err := c.IsPostgres(host, port) +func (c *PGClient) Connect(ctx context.Context, host string, port int, username, password string) (bool, error) { + ok, err := c.IsPostgres(ctx, host, port) if err != nil { return false, err } if !ok { return false, fmt.Errorf("not a postgres service") } - return memoizedconnect(host, port, username, password, "postgres") + executionId := ctx.Value("executionId").(string) + return memoizedconnect(executionId, host, port, username, password, "postgres") } // ExecuteQuery connects to Postgres database using given credentials and database name. @@ -97,8 +104,8 @@ func (c *PGClient) Connect(host string, port int, username, password string) (bo // const result = client.ExecuteQuery('acme.com', 5432, 'username', 'password', 'dbname', 'select * from users'); // log(to_json(result)); // ``` -func (c *PGClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) { - ok, err := c.IsPostgres(host, port) +func (c *PGClient) ExecuteQuery(ctx context.Context, host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) { + ok, err := c.IsPostgres(ctx, host, port) if err != nil { return nil, err } @@ -106,26 +113,28 @@ func (c *PGClient) ExecuteQuery(host string, port int, username, password, dbNam return nil, fmt.Errorf("not a postgres service") } - return memoizedexecuteQuery(host, port, username, password, dbName, query) + executionId := ctx.Value("executionId").(string) + + return memoizedexecuteQuery(executionId, host, port, username, password, dbName, query) } // @memo -func executeQuery(host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) - connStr := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", username, password, target, dbName) + connStr := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable&executionId=%s", username, password, target, dbName, executionId) db, err := sql.Open(pgwrap.PGWrapDriver, connStr) if err != nil { return nil, err } defer func() { - _ = db.Close() - }() + _ = db.Close() + }() rows, err := db.Query(query) if err != nil { @@ -148,8 +157,8 @@ func executeQuery(host string, port int, username string, password string, dbNam // const client = new postgres.PGClient; // const connected = client.ConnectWithDB('acme.com', 5432, 'username', 'password', 'dbname'); // ``` -func (c *PGClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) { - ok, err := c.IsPostgres(host, port) +func (c *PGClient) ConnectWithDB(ctx context.Context, host string, port int, username, password, dbName string) (bool, error) { + ok, err := c.IsPostgres(ctx, host, port) if err != nil { return false, err } @@ -157,16 +166,18 @@ func (c *PGClient) ConnectWithDB(host string, port int, username, password, dbNa return false, fmt.Errorf("not a postgres service") } - return memoizedconnect(host, port, username, password, dbName) + executionId := ctx.Value("executionId").(string) + + return memoizedconnect(executionId, host, port, username, password, dbName) } // @memo -func connect(host string, port int, username string, password string, dbName string) (bool, error) { +func connect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) { if host == "" || port <= 0 { return false, fmt.Errorf("invalid host or port") } - if !protocolstate.IsHostAllowed(host) { + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return false, protocolstate.ErrHostDenied.Msgf(host) } @@ -176,19 +187,24 @@ func connect(host string, port int, username string, password string, dbName str ctx, cancel := context.WithCancel(context.Background()) defer cancel() + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + db := pg.Connect(&pg.Options{ Addr: target, User: username, Password: password, Database: dbName, Dialer: func(network, addr string) (net.Conn, error) { - return protocolstate.Dialer.Dial(context.Background(), network, addr) + return dialer.Fastdialer.Dial(context.Background(), network, addr) }, IdleCheckFrequency: -1, }).WithContext(ctx).WithTimeout(10 * time.Second) defer func() { - _ = db.Close() - }() + _ = db.Close() + }() _, err := db.Exec("select 1") if err != nil { diff --git a/pkg/js/libs/rdp/memo.rdp.go b/pkg/js/libs/rdp/memo.rdp.go index c592e20e1..0c0b42012 100755 --- a/pkg/js/libs/rdp/memo.rdp.go +++ b/pkg/js/libs/rdp/memo.rdp.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisRDP(host string, port int) (IsRDPResponse, error) { +func memoizedisRDP(executionId string, host string, port int) (IsRDPResponse, error) { hash := "isRDP" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isRDP(host, port) + return isRDP(executionId, host, port) }) if err != nil { return IsRDPResponse{}, err @@ -24,11 +24,11 @@ func memoizedisRDP(host string, port int) (IsRDPResponse, error) { return IsRDPResponse{}, errors.New("could not convert cached result") } -func memoizedcheckRDPAuth(host string, port int) (CheckRDPAuthResponse, error) { +func memoizedcheckRDPAuth(executionId string, host string, port int) (CheckRDPAuthResponse, error) { hash := "checkRDPAuth" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return checkRDPAuth(host, port) + return checkRDPAuth(executionId, host, port) }) if err != nil { return CheckRDPAuthResponse{}, err diff --git a/pkg/js/libs/rdp/rdp.go b/pkg/js/libs/rdp/rdp.go index e2a7996b3..9ccffb92d 100644 --- a/pkg/js/libs/rdp/rdp.go +++ b/pkg/js/libs/rdp/rdp.go @@ -35,22 +35,28 @@ type ( // const isRDP = rdp.IsRDP('acme.com', 3389); // log(toJSON(isRDP)); // ``` -func IsRDP(host string, port int) (IsRDPResponse, error) { - return memoizedisRDP(host, port) +func IsRDP(ctx context.Context, host string, port int) (IsRDPResponse, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisRDP(executionId, host, port) } // @memo -func isRDP(host string, port int) (IsRDPResponse, error) { +func isRDP(executionId string, host string, port int) (IsRDPResponse, error) { resp := IsRDPResponse{} + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return IsRDPResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return resp, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() server, isRDP, err := rdp.DetectRDP(conn, timeout) if err != nil { @@ -88,22 +94,27 @@ type ( // const checkRDPAuth = rdp.CheckRDPAuth('acme.com', 3389); // log(toJSON(checkRDPAuth)); // ``` -func CheckRDPAuth(host string, port int) (CheckRDPAuthResponse, error) { - return memoizedcheckRDPAuth(host, port) +func CheckRDPAuth(ctx context.Context, host string, port int) (CheckRDPAuthResponse, error) { + executionId := ctx.Value("executionId").(string) + return memoizedcheckRDPAuth(executionId, host, port) } // @memo -func checkRDPAuth(host string, port int) (CheckRDPAuthResponse, error) { +func checkRDPAuth(executionId string, host string, port int) (CheckRDPAuthResponse, error) { resp := CheckRDPAuthResponse{} + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return CheckRDPAuthResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return resp, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() pluginInfo, auth, err := rdp.DetectRDPAuth(conn, timeout) if err != nil { diff --git a/pkg/js/libs/redis/memo.redis.go b/pkg/js/libs/redis/memo.redis.go index d53c44893..ab587e111 100755 --- a/pkg/js/libs/redis/memo.redis.go +++ b/pkg/js/libs/redis/memo.redis.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedgetServerInfo(host string, port int) (string, error) { +func memoizedgetServerInfo(executionId string, host string, port int) (string, error) { hash := "getServerInfo" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return getServerInfo(host, port) + return getServerInfo(executionId, host, port) }) if err != nil { return "", err @@ -24,11 +24,11 @@ func memoizedgetServerInfo(host string, port int) (string, error) { return "", errors.New("could not convert cached result") } -func memoizedconnect(host string, port int, password string) (bool, error) { +func memoizedconnect(executionId string, host string, port int, password string) (bool, error) { hash := "connect" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(password) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return connect(host, port, password) + return connect(executionId, host, port, password) }) if err != nil { return false, err @@ -40,11 +40,11 @@ func memoizedconnect(host string, port int, password string) (bool, error) { return false, errors.New("could not convert cached result") } -func memoizedgetServerInfoAuth(host string, port int, password string) (string, error) { +func memoizedgetServerInfoAuth(executionId string, host string, port int, password string) (string, error) { hash := "getServerInfoAuth" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(password) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return getServerInfoAuth(host, port, password) + return getServerInfoAuth(executionId, host, port, password) }) if err != nil { return "", err @@ -56,11 +56,11 @@ func memoizedgetServerInfoAuth(host string, port int, password string) (string, return "", errors.New("could not convert cached result") } -func memoizedisAuthenticated(host string, port int) (bool, error) { +func memoizedisAuthenticated(executionId string, host string, port int) (bool, error) { hash := "isAuthenticated" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isAuthenticated(host, port) + return isAuthenticated(executionId, host, port) }) if err != nil { return false, err diff --git a/pkg/js/libs/redis/redis.go b/pkg/js/libs/redis/redis.go index bf1f61644..84b96d86b 100644 --- a/pkg/js/libs/redis/redis.go +++ b/pkg/js/libs/redis/redis.go @@ -18,13 +18,14 @@ import ( // const redis = require('nuclei/redis'); // const info = redis.GetServerInfo('acme.com', 6379); // ``` -func GetServerInfo(host string, port int) (string, error) { - return memoizedgetServerInfo(host, port) +func GetServerInfo(ctx context.Context, host string, port int) (string, error) { + executionId := ctx.Value("executionId").(string) + return memoizedgetServerInfo(executionId, host, port) } // @memo -func getServerInfo(host string, port int) (string, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } @@ -35,8 +36,8 @@ func getServerInfo(host string, port int) (string, error) { DB: 0, // use default DB }) defer func() { - _ = client.Close() - }() + _ = client.Close() + }() // Ping the Redis server _, err := client.Ping(context.TODO()).Result() @@ -59,13 +60,14 @@ func getServerInfo(host string, port int) (string, error) { // const redis = require('nuclei/redis'); // const connected = redis.Connect('acme.com', 6379, 'password'); // ``` -func Connect(host string, port int, password string) (bool, error) { - return memoizedconnect(host, port, password) +func Connect(ctx context.Context, host string, port int, password string) (bool, error) { + executionId := ctx.Value("executionId").(string) + return memoizedconnect(executionId, host, port, password) } // @memo -func connect(host string, port int, password string) (bool, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } @@ -76,8 +78,8 @@ func connect(host string, port int, password string) (bool, error) { DB: 0, // use default DB }) defer func() { - _ = client.Close() - }() + _ = client.Close() + }() _, err := client.Ping(context.TODO()).Result() if err != nil { @@ -98,13 +100,14 @@ func connect(host string, port int, password string) (bool, error) { // const redis = require('nuclei/redis'); // const info = redis.GetServerInfoAuth('acme.com', 6379, 'password'); // ``` -func GetServerInfoAuth(host string, port int, password string) (string, error) { - return memoizedgetServerInfoAuth(host, port, password) +func GetServerInfoAuth(ctx context.Context, host string, port int, password string) (string, error) { + executionId := ctx.Value("executionId").(string) + return memoizedgetServerInfoAuth(executionId, host, port, password) } // @memo -func getServerInfoAuth(host string, port int, password string) (string, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } @@ -115,8 +118,8 @@ func getServerInfoAuth(host string, port int, password string) (string, error) { DB: 0, // use default DB }) defer func() { - _ = client.Close() - }() + _ = client.Close() + }() // Ping the Redis server _, err := client.Ping(context.TODO()).Result() @@ -139,21 +142,27 @@ func getServerInfoAuth(host string, port int, password string) (string, error) { // const redis = require('nuclei/redis'); // const isAuthenticated = redis.IsAuthenticated('acme.com', 6379); // ``` -func IsAuthenticated(host string, port int) (bool, error) { - return memoizedisAuthenticated(host, port) +func IsAuthenticated(ctx context.Context, host string, port int) (bool, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisAuthenticated(executionId, host, port) } // @memo -func isAuthenticated(host string, port int) (bool, error) { +func isAuthenticated(executionId string, host string, port int) (bool, error) { plugin := pluginsredis.REDISPlugin{} timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return false, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() _, err = plugin.Run(conn, timeout, plugins.Target{Host: host}) if err != nil { @@ -168,8 +177,9 @@ func isAuthenticated(host string, port int) (bool, error) { // const redis = require('nuclei/redis'); // const result = redis.RunLuaScript('acme.com', 6379, 'password', 'return redis.call("get", KEYS[1])'); // ``` -func RunLuaScript(host string, port int, password string, script string) (interface{}, error) { - if !protocolstate.IsHostAllowed(host) { +func RunLuaScript(ctx context.Context, host string, port int, password string, script string) (interface{}, error) { + executionId := ctx.Value("executionId").(string) + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return false, protocolstate.ErrHostDenied.Msgf(host) } @@ -180,8 +190,8 @@ func RunLuaScript(host string, port int, password string, script string) (interf DB: 0, // use default DB }) defer func() { - _ = client.Close() - }() + _ = client.Close() + }() // Ping the Redis server _, err := client.Ping(context.TODO()).Result() diff --git a/pkg/js/libs/rsync/memo.rsync.go b/pkg/js/libs/rsync/memo.rsync.go index 5cb0d0297..98bd45c49 100755 --- a/pkg/js/libs/rsync/memo.rsync.go +++ b/pkg/js/libs/rsync/memo.rsync.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisRsync(host string, port int) (IsRsyncResponse, error) { +func memoizedisRsync(executionId string, host string, port int) (IsRsyncResponse, error) { hash := "isRsync" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isRsync(host, port) + return isRsync(executionId, host, port) }) if err != nil { return IsRsyncResponse{}, err diff --git a/pkg/js/libs/rsync/rsync.go b/pkg/js/libs/rsync/rsync.go index 41ff2e5fd..a1b407395 100644 --- a/pkg/js/libs/rsync/rsync.go +++ b/pkg/js/libs/rsync/rsync.go @@ -2,6 +2,7 @@ package rsync import ( "context" + "fmt" "net" "strconv" "time" @@ -33,16 +34,21 @@ type ( // const isRsync = rsync.IsRsync('acme.com', 873); // log(toJSON(isRsync)); // ``` -func IsRsync(host string, port int) (IsRsyncResponse, error) { - return memoizedisRsync(host, port) +func IsRsync(ctx context.Context, host string, port int) (IsRsyncResponse, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisRsync(executionId, host, port) } // @memo -func isRsync(host string, port int) (IsRsyncResponse, error) { +func isRsync(executionId string, host string, port int) (IsRsyncResponse, error) { resp := IsRsyncResponse{} timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return IsRsyncResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) if err != nil { return resp, err } diff --git a/pkg/js/libs/smb/memo.smb.go b/pkg/js/libs/smb/memo.smb.go index 51d6584f0..96bdb036a 100755 --- a/pkg/js/libs/smb/memo.smb.go +++ b/pkg/js/libs/smb/memo.smb.go @@ -10,11 +10,11 @@ import ( "github.com/zmap/zgrab2/lib/smb/smb" ) -func memoizedconnectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { +func memoizedconnectSMBInfoMode(executionId string, host string, port int) (*smb.SMBLog, error) { hash := "connectSMBInfoMode" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return connectSMBInfoMode(host, port) + return connectSMBInfoMode(executionId, host, port) }) if err != nil { return nil, err @@ -26,11 +26,11 @@ func memoizedconnectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { return nil, errors.New("could not convert cached result") } -func memoizedlistShares(host string, port int, user string, password string) ([]string, error) { +func memoizedlistShares(executionId string, host string, port int, user string, password string) ([]string, error) { hash := "listShares" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(user) + ":" + fmt.Sprint(password) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return listShares(host, port, user, password) + return listShares(executionId, host, port, user, password) }) if err != nil { return []string{}, err diff --git a/pkg/js/libs/smb/memo.smb_private.go b/pkg/js/libs/smb/memo.smb_private.go index fe47d1a28..c209a61f1 100755 --- a/pkg/js/libs/smb/memo.smb_private.go +++ b/pkg/js/libs/smb/memo.smb_private.go @@ -12,11 +12,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedcollectSMBv2Metadata(host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) { +func memoizedcollectSMBv2Metadata(executionId string, host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) { hash := "collectSMBv2Metadata" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(timeout) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return collectSMBv2Metadata(host, port, timeout) + return collectSMBv2Metadata(executionId, host, port, timeout) }) if err != nil { return nil, err diff --git a/pkg/js/libs/smb/memo.smbghost.go b/pkg/js/libs/smb/memo.smbghost.go index 25e9d1878..43eee8441 100755 --- a/pkg/js/libs/smb/memo.smbghost.go +++ b/pkg/js/libs/smb/memo.smbghost.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizeddetectSMBGhost(host string, port int) (bool, error) { +func memoizeddetectSMBGhost(executionId string, host string, port int) (bool, error) { hash := "detectSMBGhost" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return detectSMBGhost(host, port) + return detectSMBGhost(executionId, host, port) }) if err != nil { return false, err diff --git a/pkg/js/libs/smb/smb.go b/pkg/js/libs/smb/smb.go index 4309b6e42..7dc2dc83b 100644 --- a/pkg/js/libs/smb/smb.go +++ b/pkg/js/libs/smb/smb.go @@ -34,17 +34,22 @@ type ( // const info = client.ConnectSMBInfoMode('acme.com', 445); // log(to_json(info)); // ``` -func (c *SMBClient) ConnectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { - return memoizedconnectSMBInfoMode(host, port) +func (c *SMBClient) ConnectSMBInfoMode(ctx context.Context, host string, port int) (*smb.SMBLog, error) { + executionId := ctx.Value("executionId").(string) + return memoizedconnectSMBInfoMode(executionId, host, port) } // @memo -func connectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return nil, err } @@ -56,13 +61,13 @@ func connectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { } // try to negotiate SMBv1 - conn, err = protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + conn, err = dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return nil, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() result, err = getSMBInfo(conn, true, true) if err != nil { return result, nil @@ -81,12 +86,13 @@ func connectSMBInfoMode(host string, port int) (*smb.SMBLog, error) { // const metadata = client.ListSMBv2Metadata('acme.com', 445); // log(to_json(metadata)); // ``` -func (c *SMBClient) ListSMBv2Metadata(host string, port int) (*plugins.ServiceSMB, error) { - if !protocolstate.IsHostAllowed(host) { +func (c *SMBClient) ListSMBv2Metadata(ctx context.Context, host string, port int) (*plugins.ServiceSMB, error) { + executionId := ctx.Value("executionId").(string) + if !protocolstate.IsHostAllowed(executionId, host) { // host is not valid according to network policy return nil, protocolstate.ErrHostDenied.Msgf(host) } - return memoizedcollectSMBv2Metadata(host, port, 5*time.Second) + return memoizedcollectSMBv2Metadata(executionId, host, port, 5*time.Second) } // ListShares tries to connect to provided host and port @@ -104,23 +110,29 @@ func (c *SMBClient) ListSMBv2Metadata(host string, port int) (*plugins.ServiceSM // } // // ``` -func (c *SMBClient) ListShares(host string, port int, user, password string) ([]string, error) { - return memoizedlistShares(host, port, user, password) +func (c *SMBClient) ListShares(ctx context.Context, host string, port int, user, password string) ([]string, error) { + executionId := ctx.Value("executionId").(string) + return memoizedlistShares(executionId, host, port, user, password) } // @memo -func listShares(host string, port int, user string, password string) ([]string, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { return nil, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() d := &smb2.Dialer{ Initiator: &smb2.NTLMInitiator{ diff --git a/pkg/js/libs/smb/smb_private.go b/pkg/js/libs/smb/smb_private.go index a9d655ce1..353816793 100644 --- a/pkg/js/libs/smb/smb_private.go +++ b/pkg/js/libs/smb/smb_private.go @@ -16,17 +16,22 @@ import ( // collectSMBv2Metadata collects metadata for SMBv2 services. // @memo -func collectSMBv2Metadata(host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) { +func collectSMBv2Metadata(executionId string, host string, port int, timeout time.Duration) (*plugins.ServiceSMB, error) { if timeout == 0 { timeout = 5 * time.Second } - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return nil, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) if err != nil { return nil, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() metadata, err := smb.DetectSMBv2(conn, timeout) if err != nil { diff --git a/pkg/js/libs/smb/smbghost.go b/pkg/js/libs/smb/smbghost.go index 8f973e096..69ddcca1e 100644 --- a/pkg/js/libs/smb/smbghost.go +++ b/pkg/js/libs/smb/smbghost.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "net" "strconv" "time" @@ -25,18 +26,23 @@ const ( // const smb = require('nuclei/smb'); // const isSMBGhost = smb.DetectSMBGhost('acme.com', 445); // ``` -func (c *SMBClient) DetectSMBGhost(host string, port int) (bool, error) { - return memoizeddetectSMBGhost(host, port) +func (c *SMBClient) DetectSMBGhost(ctx context.Context, host string, port int) (bool, error) { + executionId := ctx.Value("executionId").(string) + return memoizeddetectSMBGhost(executionId, host, port) } // @memo -func detectSMBGhost(host string, port int) (bool, error) { - if !protocolstate.IsHostAllowed(host) { +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.Msgf(host) } addr := net.JoinHostPort(host, strconv.Itoa(port)) - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", addr) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", addr) if err != nil { return false, err diff --git a/pkg/js/libs/smtp/smtp.go b/pkg/js/libs/smtp/smtp.go index c4856227d..d4a7e0227 100644 --- a/pkg/js/libs/smtp/smtp.go +++ b/pkg/js/libs/smtp/smtp.go @@ -8,7 +8,7 @@ import ( "strconv" "time" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/praetorian-inc/fingerprintx/pkg/plugins" "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" @@ -65,8 +65,10 @@ func NewSMTPClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Objec c.host = host c.port = port + executionId := c.nj.ExecutionId() + // check if this is allowed address - c.nj.Require(protocolstate.IsHostAllowed(host+":"+port), protocolstate.ErrHostDenied.Msgf(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) @@ -86,13 +88,20 @@ func (c *Client) IsSMTP() (SMTPResponse, error) { c.nj.Require(c.port != "", "port cannot be empty") timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(c.host, c.port)) + + executionId := c.nj.ExecutionId() + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return SMTPResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(c.host, c.port)) if err != nil { return resp, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() smtpPlugin := pluginsmtp.SMTPPlugin{} service, err := smtpPlugin.Run(conn, timeout, plugins.Target{Host: c.host}) @@ -123,14 +132,20 @@ func (c *Client) IsOpenRelay(msg *SMTPMessage) (bool, error) { c.nj.Require(c.host != "", "host cannot be empty") c.nj.Require(c.port != "", "port cannot be empty") + executionId := c.nj.ExecutionId() + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + addr := net.JoinHostPort(c.host, c.port) - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", addr) + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", addr) if err != nil { return false, err } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() client, err := smtp.NewClient(conn, c.host) if err != nil { return false, err diff --git a/pkg/js/libs/ssh/ssh.go b/pkg/js/libs/ssh/ssh.go index 32cd870fc..17b35afe5 100644 --- a/pkg/js/libs/ssh/ssh.go +++ b/pkg/js/libs/ssh/ssh.go @@ -1,6 +1,7 @@ package ssh import ( + "context" "fmt" "strings" "time" @@ -45,12 +46,14 @@ func (c *SSHClient) SetTimeout(sec int) { // const client = new ssh.SSHClient(); // const connected = client.Connect('acme.com', 22, 'username', 'password'); // ``` -func (c *SSHClient) Connect(host string, port int, username, password string) (bool, error) { +func (c *SSHClient) Connect(ctx context.Context, host string, port int, username, password string) (bool, error) { + executionId := ctx.Value("executionId").(string) conn, err := connect(&connectOptions{ - Host: host, - Port: port, - User: username, - Password: password, + Host: host, + Port: port, + User: username, + Password: password, + ExecutionId: executionId, }) if err != nil { return false, err @@ -71,12 +74,14 @@ func (c *SSHClient) Connect(host string, port int, username, password string) (b // const privateKey = `-----BEGIN RSA PRIVATE KEY----- ...`; // const connected = client.ConnectWithKey('acme.com', 22, 'username', privateKey); // ``` -func (c *SSHClient) ConnectWithKey(host string, port int, username, key string) (bool, error) { +func (c *SSHClient) ConnectWithKey(ctx context.Context, host string, port int, username, key string) (bool, error) { + executionId := ctx.Value("executionId").(string) conn, err := connect(&connectOptions{ - Host: host, - Port: port, - User: username, - PrivateKey: key, + Host: host, + Port: port, + User: username, + PrivateKey: key, + ExecutionId: executionId, }) if err != nil { @@ -100,10 +105,12 @@ func (c *SSHClient) ConnectWithKey(host string, port int, username, key string) // const info = client.ConnectSSHInfoMode('acme.com', 22); // log(to_json(info)); // ``` -func (c *SSHClient) ConnectSSHInfoMode(host string, port int) (*ssh.HandshakeLog, error) { +func (c *SSHClient) ConnectSSHInfoMode(ctx context.Context, host string, port int) (*ssh.HandshakeLog, error) { + executionId := ctx.Value("executionId").(string) return memoizedconnectSSHInfoMode(&connectOptions{ - Host: host, - Port: port, + Host: host, + Port: port, + ExecutionId: executionId, }) } @@ -129,8 +136,8 @@ func (c *SSHClient) Run(cmd string) (string, error) { return "", err } defer func() { - _ = session.Close() - }() + _ = session.Close() + }() data, err := session.Output(cmd) if err != nil { @@ -159,12 +166,13 @@ func (c *SSHClient) Close() (bool, error) { // unexported functions type connectOptions struct { - Host string - Port int - User string - Password string - PrivateKey string - Timeout time.Duration // default 10s + Host string + Port int + User string + Password string + PrivateKey string + Timeout time.Duration // default 10s + ExecutionId string } func (c *connectOptions) validate() error { @@ -174,7 +182,7 @@ func (c *connectOptions) validate() error { if c.Port <= 0 { return errorutil.New("port is required") } - if !protocolstate.IsHostAllowed(c.Host) { + if !protocolstate.IsHostAllowed(c.ExecutionId, c.Host) { // host is not valid according to network policy return protocolstate.ErrHostDenied.Msgf(c.Host) } @@ -206,8 +214,8 @@ func connectSSHInfoMode(opts *connectOptions) (*ssh.HandshakeLog, error) { return nil, err } defer func() { - _ = client.Close() - }() + _ = client.Close() + }() return data, nil } diff --git a/pkg/js/libs/telnet/memo.telnet.go b/pkg/js/libs/telnet/memo.telnet.go index 0e29a5e73..0c02169f6 100755 --- a/pkg/js/libs/telnet/memo.telnet.go +++ b/pkg/js/libs/telnet/memo.telnet.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisTelnet(host string, port int) (IsTelnetResponse, error) { +func memoizedisTelnet(executionId string, host string, port int) (IsTelnetResponse, error) { hash := "isTelnet" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isTelnet(host, port) + return isTelnet(executionId, host, port) }) if err != nil { return IsTelnetResponse{}, err diff --git a/pkg/js/libs/telnet/telnet.go b/pkg/js/libs/telnet/telnet.go index d585b2af7..db220309f 100644 --- a/pkg/js/libs/telnet/telnet.go +++ b/pkg/js/libs/telnet/telnet.go @@ -2,6 +2,7 @@ package telnet import ( "context" + "fmt" "net" "strconv" "time" @@ -33,16 +34,22 @@ type ( // const isTelnet = telnet.IsTelnet('acme.com', 23); // log(toJSON(isTelnet)); // ``` -func IsTelnet(host string, port int) (IsTelnetResponse, error) { - return memoizedisTelnet(host, port) +func IsTelnet(ctx context.Context, host string, port int) (IsTelnetResponse, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisTelnet(executionId, host, port) } // @memo -func isTelnet(host string, port int) (IsTelnetResponse, error) { +func isTelnet(executionId string, host string, port int) (IsTelnetResponse, error) { resp := IsTelnetResponse{} timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return IsTelnetResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) if err != nil { return resp, err } diff --git a/pkg/js/libs/vnc/memo.vnc.go b/pkg/js/libs/vnc/memo.vnc.go index 8e2fd4546..c0639d216 100755 --- a/pkg/js/libs/vnc/memo.vnc.go +++ b/pkg/js/libs/vnc/memo.vnc.go @@ -8,11 +8,11 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" ) -func memoizedisVNC(host string, port int) (IsVNCResponse, error) { +func memoizedisVNC(executionId string, host string, port int) (IsVNCResponse, error) { hash := "isVNC" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) { - return isVNC(host, port) + return isVNC(executionId, host, port) }) if err != nil { return IsVNCResponse{}, err diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index a3d72499c..bd28ad692 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -2,6 +2,7 @@ package vnc import ( "context" + "fmt" "net" "strconv" "time" @@ -34,16 +35,21 @@ type ( // const isVNC = vnc.IsVNC('acme.com', 5900); // log(toJSON(isVNC)); // ``` -func IsVNC(host string, port int) (IsVNCResponse, error) { - return memoizedisVNC(host, port) +func IsVNC(ctx context.Context, host string, port int) (IsVNCResponse, error) { + executionId := ctx.Value("executionId").(string) + return memoizedisVNC(executionId, host, port) } // @memo -func isVNC(host string, port int) (IsVNCResponse, error) { +func isVNC(executionId string, host string, port int) (IsVNCResponse, error) { resp := IsVNCResponse{} timeout := 5 * time.Second - conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return IsVNCResponse{}, fmt.Errorf("dialers not initialized for %s", executionId) + } + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) if err != nil { return resp, err } diff --git a/pkg/js/utils/nucleijs.go b/pkg/js/utils/nucleijs.go index 9d9e3f4ec..e78ea6f92 100644 --- a/pkg/js/utils/nucleijs.go +++ b/pkg/js/utils/nucleijs.go @@ -6,7 +6,7 @@ import ( "strings" "sync" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" ) // temporary on demand runtime to throw errors when vm is not available @@ -42,6 +42,14 @@ func (j *NucleiJS) runtime() *goja.Runtime { return j.vm } +func (j *NucleiJS) ExecutionId() string { + executionId, ok := j.vm.GetContextValue("executionId") + if !ok { + return "" + } + return executionId.(string) +} + // see: https://arc.net/l/quote/wpenftpc for throwing docs // ThrowError throws an error in goja runtime if is not nil diff --git a/pkg/js/utils/pgwrap/pgwrap.go b/pkg/js/utils/pgwrap/pgwrap.go index d1b82f7ab..08c396fdb 100644 --- a/pkg/js/utils/pgwrap/pgwrap.go +++ b/pkg/js/utils/pgwrap/pgwrap.go @@ -4,7 +4,9 @@ import ( "context" "database/sql" "database/sql/driver" + "fmt" "net" + "net/url" "time" "github.com/lib/pq" @@ -17,21 +19,33 @@ const ( ) type pgDial struct { - fd *fastdialer.Dialer + executionId string } func (p *pgDial) Dial(network, address string) (net.Conn, error) { - return p.fd.Dial(context.TODO(), network, address) + dialers := protocolstate.GetDialersWithId(p.executionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", p.executionId) + } + return dialers.Fastdialer.Dial(context.TODO(), network, address) } func (p *pgDial) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) { + dialers := protocolstate.GetDialersWithId(p.executionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", p.executionId) + } ctx, cancel := context.WithTimeoutCause(context.Background(), timeout, fastdialer.ErrDialTimeout) defer cancel() - return p.fd.Dial(ctx, network, address) + return dialers.Fastdialer.Dial(ctx, network, address) } func (p *pgDial) DialContext(ctx context.Context, network, address string) (net.Conn, error) { - return p.fd.Dial(ctx, network, address) + dialers := protocolstate.GetDialersWithId(p.executionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", p.executionId) + } + return dialers.Fastdialer.Dial(ctx, network, address) } // Unfortunately lib/pq does not provide easy to customize or @@ -45,7 +59,18 @@ type PgDriver struct{} // Most users should only use it through database/sql package from the standard // library. func (d PgDriver) Open(name string) (driver.Conn, error) { - return pq.DialOpen(&pgDial{fd: protocolstate.Dialer}, name) + // Parse the connection string to get executionId + u, err := url.Parse(name) + if err != nil { + return nil, fmt.Errorf("invalid connection string: %v", err) + } + values := u.Query() + executionId := values.Get("executionId") + // Remove executionId from the connection string + values.Del("executionId") + u.RawQuery = values.Encode() + + return pq.DialOpen(&pgDial{executionId: executionId}, u.String()) } func init() { diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index ad1c0b234..ef653ff13 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -8,9 +8,9 @@ import ( "strings" "time" + "github.com/Mzack9999/goja" "github.com/alecthomas/chroma/quick" "github.com/ditashi/jsbeautifier-go/jsbeautifier" - "github.com/dop251/goja" "github.com/pkg/errors" "github.com/projectdiscovery/gologger" @@ -201,6 +201,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa result, err := request.options.JsCompiler.ExecuteWithOptions(request.preConditionCompiled, args, &compiler.ExecuteOptions{ + ExecutionId: request.options.Options.ExecutionId, TimeoutVariants: request.options.Options.GetTimeouts(), Source: &request.PreCondition, Callback: registerPreConditionFunctions, @@ -431,3 +432,8 @@ func prettyPrint(templateId string, buff string) { } gologger.Debug().Msgf(" [%v] Pre-condition Code:\n\n%v\n\n", templateId, strings.Join(final, "\n")) } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/code/helpers.go b/pkg/protocols/code/helpers.go index f67144e79..4e8477610 100644 --- a/pkg/protocols/code/helpers.go +++ b/pkg/protocols/code/helpers.go @@ -3,7 +3,7 @@ package code import ( goruntime "runtime" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" osutils "github.com/projectdiscovery/utils/os" ) diff --git a/pkg/protocols/common/automaticscan/automaticscan.go b/pkg/protocols/common/automaticscan/automaticscan.go index 00ed60e69..698c7f05e 100644 --- a/pkg/protocols/common/automaticscan/automaticscan.go +++ b/pkg/protocols/common/automaticscan/automaticscan.go @@ -44,7 +44,7 @@ const ( // Options contains configuration options for automatic scan service type Options struct { - ExecuterOpts protocols.ExecutorOptions + ExecuterOpts *protocols.ExecutorOptions Store *loader.Store Engine *core.Engine Target provider.InputProvider @@ -52,7 +52,7 @@ type Options struct { // Service is a service for automatic scan execution type Service struct { - opts protocols.ExecutorOptions + opts *protocols.ExecutorOptions store *loader.Store engine *core.Engine target provider.InputProvider @@ -188,7 +188,7 @@ func (s *Service) executeAutomaticScanOnTarget(input *contextargs.MetaInput) { execOptions.Progress = &testutils.MockProgressClient{} // stats are not supported yet due to centralized logic and cannot be reinitialized eng.SetExecuterOptions(execOptions) - tmp := eng.ExecuteScanWithOpts(context.Background(), finalTemplates, provider.NewSimpleInputProviderWithUrls(input.Input), true) + tmp := eng.ExecuteScanWithOpts(context.Background(), finalTemplates, provider.NewSimpleInputProviderWithUrls(s.opts.Options.ExecutionId, input.Input), true) s.hasResults.Store(tmp.Load()) } diff --git a/pkg/protocols/common/automaticscan/util.go b/pkg/protocols/common/automaticscan/util.go index e63afdddf..edbe6175f 100644 --- a/pkg/protocols/common/automaticscan/util.go +++ b/pkg/protocols/common/automaticscan/util.go @@ -2,7 +2,6 @@ package automaticscan import ( "github.com/pkg/errors" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/templates" "github.com/projectdiscovery/nuclei/v3/pkg/types" @@ -46,14 +45,14 @@ func LoadTemplatesWithTags(opts Options, templateDirs []string, tags []string, l finalTemplates, clusterCount := templates.ClusterTemplates(finalTemplates, opts.ExecuterOpts) totalReqAfterClustering := getRequestCount(finalTemplates) * int(opts.Target.Count()) if totalReqAfterClustering < totalReqBeforeCluster && logInfo { - gologger.Info().Msgf("Automatic scan tech-detect: Templates clustered: %d (Reduced %d Requests)", clusterCount, totalReqBeforeCluster-totalReqAfterClustering) + opts.ExecuterOpts.Logger.Info().Msgf("Automatic scan tech-detect: Templates clustered: %d (Reduced %d Requests)", clusterCount, totalReqBeforeCluster-totalReqAfterClustering) } } // log template loaded if VerboseVerbose flag is set if opts.ExecuterOpts.Options.VerboseVerbose { for _, tpl := range finalTemplates { - gologger.Print().Msgf("%s\n", templates.TemplateLogMessage(tpl.ID, + opts.ExecuterOpts.Logger.Print().Msgf("%s\n", templates.TemplateLogMessage(tpl.ID, types.ToString(tpl.Info.Name), tpl.Info.Authors.ToSlice(), tpl.Info.SeverityHolder.Severity)) diff --git a/pkg/protocols/common/interactsh/options.go b/pkg/protocols/common/interactsh/options.go index ca3dd459c..70273ce92 100644 --- a/pkg/protocols/common/interactsh/options.go +++ b/pkg/protocols/common/interactsh/options.go @@ -3,6 +3,7 @@ package interactsh import ( "time" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/interactsh/pkg/client" "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/frequency" "github.com/projectdiscovery/nuclei/v3/pkg/output" @@ -46,6 +47,8 @@ type Options struct { NoInteractsh bool // NoColor disables printing colors for matches NoColor bool + // Logger is the shared logging instance + Logger *gologger.Logger FuzzParamsFrequency *frequency.Tracker StopAtFirstMatch bool diff --git a/pkg/protocols/common/protocolinit/init.go b/pkg/protocols/common/protocolinit/init.go index 20b7b7a10..bdb6a6f3c 100644 --- a/pkg/protocols/common/protocolinit/init.go +++ b/pkg/protocols/common/protocolinit/init.go @@ -38,6 +38,6 @@ func Init(options *types.Options) error { return nil } -func Close() { - protocolstate.Close() +func Close(executionId string) { + protocolstate.Close(executionId) } diff --git a/pkg/protocols/common/protocolstate/context.go b/pkg/protocols/common/protocolstate/context.go new file mode 100644 index 000000000..a6dbb46fb --- /dev/null +++ b/pkg/protocols/common/protocolstate/context.go @@ -0,0 +1,46 @@ +package protocolstate + +import ( + "context" + + "github.com/rs/xid" +) + +// contextKey is a type for context keys +type ContextKey string + +type ExecutionContext struct { + ExecutionID string +} + +// executionIDKey is the key used to store execution ID in context +const executionIDKey ContextKey = "execution_id" + +// WithExecutionID adds an execution ID to the context +func WithExecutionID(ctx context.Context, executionContext *ExecutionContext) context.Context { + return context.WithValue(ctx, executionIDKey, executionContext) +} + +// HasExecutionID checks if the context has an execution ID +func HasExecutionContext(ctx context.Context) bool { + _, ok := ctx.Value(executionIDKey).(*ExecutionContext) + return ok +} + +// GetExecutionID retrieves the execution ID from the context +// Returns empty string if no execution ID is set +func GetExecutionContext(ctx context.Context) *ExecutionContext { + if id, ok := ctx.Value(executionIDKey).(*ExecutionContext); ok { + return id + } + return nil +} + +// WithAutoExecutionContext creates a new context with an automatically generated execution ID +// If the input context already has an execution ID, it will be preserved +func WithAutoExecutionContext(ctx context.Context) context.Context { + if HasExecutionContext(ctx) { + return ctx + } + return WithExecutionID(ctx, &ExecutionContext{ExecutionID: xid.New().String()}) +} diff --git a/pkg/protocols/common/protocolstate/dialers.go b/pkg/protocols/common/protocolstate/dialers.go new file mode 100644 index 000000000..91bdbae51 --- /dev/null +++ b/pkg/protocols/common/protocolstate/dialers.go @@ -0,0 +1,23 @@ +package protocolstate + +import ( + "sync" + + "github.com/projectdiscovery/fastdialer/fastdialer" + "github.com/projectdiscovery/networkpolicy" + "github.com/projectdiscovery/rawhttp" + "github.com/projectdiscovery/retryablehttp-go" + mapsutil "github.com/projectdiscovery/utils/maps" +) + +type Dialers struct { + Fastdialer *fastdialer.Dialer + RawHTTPClient *rawhttp.Client + DefaultHTTPClient *retryablehttp.Client + HTTPClientPool *mapsutil.SyncLockMap[string, *retryablehttp.Client] + NetworkPolicy *networkpolicy.NetworkPolicy + LocalFileAccessAllowed bool + RestrictLocalNetworkAccess bool + + sync.Mutex +} diff --git a/pkg/protocols/common/protocolstate/file.go b/pkg/protocols/common/protocolstate/file.go index 199aa44f2..9475aac0f 100644 --- a/pkg/protocols/common/protocolstate/file.go +++ b/pkg/protocols/common/protocolstate/file.go @@ -9,8 +9,8 @@ import ( ) var ( - // lfaAllowed means local file access is allowed - lfaAllowed bool + // LfaAllowed means local file access is allowed + LfaAllowed bool ) // Normalizepath normalizes path and returns absolute path @@ -18,7 +18,8 @@ var ( // this respects the sandbox rules and only loads files from // allowed directories func NormalizePath(filePath string) (string, error) { - if lfaAllowed { + // TODO: this should be tied to executionID + if LfaAllowed { return filePath, nil } cleaned, err := fileutil.ResolveNClean(filePath, config.DefaultConfig.GetTemplateDir()) @@ -32,8 +33,3 @@ func NormalizePath(filePath string) (string, error) { } return "", errorutil.New("path %v is outside nuclei-template directory and -lfa is not enabled", filePath) } - -// IsLFAAllowed returns true if local file access is allowed -func IsLFAAllowed() bool { - return lfaAllowed -} diff --git a/pkg/protocols/common/protocolstate/headless.go b/pkg/protocols/common/protocolstate/headless.go index 755d367b9..4012e2da6 100644 --- a/pkg/protocols/common/protocolstate/headless.go +++ b/pkg/protocols/common/protocolstate/headless.go @@ -1,34 +1,46 @@ package protocolstate import ( + "context" "net" "strings" "github.com/go-rod/rod" "github.com/go-rod/rod/lib/proto" "github.com/projectdiscovery/networkpolicy" + "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" stringsutil "github.com/projectdiscovery/utils/strings" urlutil "github.com/projectdiscovery/utils/url" "go.uber.org/multierr" ) -// initalize state of headless protocol +// initialize state of headless protocol var ( - ErrURLDenied = errorutil.NewWithFmt("headless: url %v dropped by rule: %v") - ErrHostDenied = errorutil.NewWithFmt("host %v dropped by network policy") - NetworkPolicy *networkpolicy.NetworkPolicy - allowLocalFileAccess bool + 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) + if execCtx == nil { + return nil + } + dialers, ok := dialers.Get(execCtx.ExecutionID) + if !ok || dialers == nil { + return nil + } + return dialers.NetworkPolicy +} + // ValidateNFailRequest validates and fails request // if the request does not respect the rules, it will be canceled with reason -func ValidateNFailRequest(page *rod.Page, e *proto.FetchRequestPaused) error { +func ValidateNFailRequest(options *types.Options, page *rod.Page, e *proto.FetchRequestPaused) error { reqURL := e.Request.URL normalized := strings.ToLower(reqURL) // normalize url to lowercase normalized = strings.TrimSpace(normalized) // trim leading & trailing whitespaces - if !allowLocalFileAccess && stringsutil.HasPrefixI(normalized, "file:") { + if !IsLfaAllowed(options) && stringsutil.HasPrefixI(normalized, "file:") { return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "use of file:// protocol disabled use '-lfa' to enable")) } // validate potential invalid schemes @@ -36,7 +48,7 @@ func ValidateNFailRequest(page *rod.Page, e *proto.FetchRequestPaused) error { if stringsutil.HasPrefixAnyI(normalized, "ftp:", "externalfile:", "chrome:", "chrome-extension:") { return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "protocol blocked by network policy")) } - if !isValidHost(reqURL) { + if !isValidHost(options, reqURL) { return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "address blocked by network policy")) } return nil @@ -52,54 +64,90 @@ func FailWithReason(page *rod.Page, e *proto.FetchRequestPaused) error { } // InitHeadless initializes headless protocol state -func InitHeadless(localFileAccess bool, np *networkpolicy.NetworkPolicy) { - allowLocalFileAccess = localFileAccess - if np != nil { - NetworkPolicy = np +func InitHeadless(options *types.Options) { + dialers, ok := dialers.Get(options.ExecutionId) + if ok && dialers != nil { + dialers.Lock() + dialers.LocalFileAccessAllowed = options.AllowLocalFileAccess + dialers.RestrictLocalNetworkAccess = options.RestrictLocalNetworkAccess + dialers.Unlock() } } +// AllowLocalFileAccess returns whether local file access is allowed +func IsLfaAllowed(options *types.Options) bool { + dialers, ok := dialers.Get(options.ExecutionId) + if ok && dialers != nil { + dialers.Lock() + defer dialers.Unlock() + + return dialers.LocalFileAccessAllowed + } + return false +} + +func IsRestrictLocalNetworkAccess(options *types.Options) bool { + dialers, ok := dialers.Get(options.ExecutionId) + if ok && dialers != nil { + dialers.Lock() + defer dialers.Unlock() + + return dialers.RestrictLocalNetworkAccess + } + return false +} + // isValidHost checks if the host is valid (only limited to http/https protocols) -func isValidHost(targetUrl string) bool { +func isValidHost(options *types.Options, targetUrl string) bool { if !stringsutil.HasPrefixAny(targetUrl, "http:", "https:") { return true } - if NetworkPolicy == nil { + + dialers, ok := dialers.Get(options.ExecutionId) + if !ok { return true } + + np := dialers.NetworkPolicy + if !ok || np == nil { + return true + } + urlx, err := urlutil.Parse(targetUrl) if err != nil { // not a valid url return false } targetUrl = urlx.Hostname() - _, ok := NetworkPolicy.ValidateHost(targetUrl) + _, ok = np.ValidateHost(targetUrl) return ok } // IsHostAllowed checks if the host is allowed by network policy -func IsHostAllowed(targetUrl string) bool { - if NetworkPolicy == nil { +func IsHostAllowed(executionId string, targetUrl string) bool { + dialers, ok := dialers.Get(executionId) + if !ok { return true } + + np := dialers.NetworkPolicy + if !ok || np == nil { + return true + } + sepCount := strings.Count(targetUrl, ":") if sepCount > 1 { // most likely a ipv6 address (parse url and validate host) - return NetworkPolicy.Validate(targetUrl) + return np.Validate(targetUrl) } if sepCount == 1 { host, _, _ := net.SplitHostPort(targetUrl) - if _, ok := NetworkPolicy.ValidateHost(host); !ok { + if _, ok := np.ValidateHost(host); !ok { return false } return true - // portInt, _ := strconv.Atoi(port) - // fixme: broken port validation logic in networkpolicy - // if !NetworkPolicy.ValidatePort(portInt) { - // return false - // } } // just a hostname or ip without port - _, ok := NetworkPolicy.ValidateHost(targetUrl) + _, ok = np.ValidateHost(targetUrl) return ok } diff --git a/pkg/protocols/common/protocolstate/js.go b/pkg/protocols/common/protocolstate/js.go index 9e522db47..79fc654c0 100644 --- a/pkg/protocols/common/protocolstate/js.go +++ b/pkg/protocols/common/protocolstate/js.go @@ -1,8 +1,8 @@ package protocolstate import ( - "github.com/dop251/goja" - "github.com/dop251/goja/parser" + "github.com/Mzack9999/goja" + "github.com/Mzack9999/goja/parser" "github.com/projectdiscovery/gologger" ) diff --git a/pkg/protocols/common/protocolstate/state.go b/pkg/protocols/common/protocolstate/state.go index 89c5eb355..9f9a96a06 100644 --- a/pkg/protocols/common/protocolstate/state.go +++ b/pkg/protocols/common/protocolstate/state.go @@ -5,7 +5,6 @@ import ( "fmt" "net" "net/url" - "sync" "github.com/go-sql-driver/mysql" "github.com/pkg/errors" @@ -16,32 +15,54 @@ import ( "github.com/projectdiscovery/networkpolicy" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/nuclei/v3/pkg/utils/expand" + "github.com/projectdiscovery/retryablehttp-go" + mapsutil "github.com/projectdiscovery/utils/maps" ) -// Dialer is a shared fastdialer instance for host DNS resolution var ( - muDialer sync.RWMutex - Dialer *fastdialer.Dialer + dialers *mapsutil.SyncLockMap[string, *Dialers] ) -func GetDialer() *fastdialer.Dialer { - muDialer.RLock() - defer muDialer.RUnlock() - - return Dialer +func init() { + dialers = mapsutil.NewSyncLockMap[string, *Dialers]() } -func ShouldInit() bool { - return Dialer == nil +func GetDialers(ctx context.Context) *Dialers { + executionContext := GetExecutionContext(ctx) + dialers, ok := dialers.Get(executionContext.ExecutionID) + if !ok { + return nil + } + return dialers } -// Init creates the Dialer instance based on user configuration +func GetDialersWithId(id string) *Dialers { + dialers, ok := dialers.Get(id) + if !ok { + return nil + } + return dialers +} + +func ShouldInit(id string) bool { + dialer, ok := dialers.Get(id) + if !ok { + return true + } + return dialer == nil +} + +// Init creates the Dialers instance based on user configuration func Init(options *types.Options) error { - if Dialer != nil { + if GetDialersWithId(options.ExecutionId) != nil { return nil } - lfaAllowed = options.AllowLocalFileAccess + return initDialers(options) +} + +// initDialers is the internal implementation of Init +func initDialers(options *types.Options) error { opts := fastdialer.DefaultOptions opts.DialerTimeout = options.GetTimeouts().DialTimeout if options.DialerKeepAlive > 0 { @@ -66,8 +87,6 @@ func Init(options *types.Options) error { DenyList: expandedDenyList, } opts.WithNetworkPolicyOptions = npOptions - NetworkPolicy, _ = networkpolicy.New(*npOptions) - InitHeadless(options.AllowLocalFileAccess, NetworkPolicy) switch { case options.SourceIP != "" && options.Interface != "": @@ -152,7 +171,17 @@ func Init(options *types.Options) error { if err != nil { return errors.Wrap(err, "could not create dialer") } - Dialer = dialer + + networkPolicy, _ := networkpolicy.New(*npOptions) + + dialersInstance := &Dialers{ + Fastdialer: dialer, + NetworkPolicy: networkPolicy, + HTTPClientPool: mapsutil.NewSyncLockMap[string, *retryablehttp.Client](), + LocalFileAccessAllowed: options.AllowLocalFileAccess, + } + + _ = dialers.Set(options.ExecutionId, dialersInstance) // Set a custom dialer for the "nucleitcp" protocol. This is just plain TCP, but it's registered // with a different name so that we do not clobber the "tcp" dialer in the event that nuclei is @@ -164,11 +193,17 @@ func Init(options *types.Options) error { addr += ":3306" } - return Dialer.Dial(ctx, "tcp", addr) + executionId := ctx.Value("executionId").(string) + dialer := GetDialersWithId(executionId) + return dialer.Fastdialer.Dial(ctx, "tcp", addr) }) StartActiveMemGuardian(context.Background()) + // TODO: this should be tied to executionID + // overidde global settings with latest options + LfaAllowed = options.AllowLocalFileAccess + return nil } @@ -226,13 +261,19 @@ func interfaceAddresses(interfaceName string) ([]net.Addr, error) { } // Close closes the global shared fastdialer -func Close() { - muDialer.Lock() - defer muDialer.Unlock() - - if Dialer != nil { - Dialer.Close() - Dialer = nil +func Close(executionId string) { + dialersInstance, ok := dialers.Get(executionId) + if !ok { + return + } + + if dialersInstance != nil { + dialersInstance.Fastdialer.Close() + } + + dialers.Delete(executionId) + + if dialers.IsEmpty() { + StopActiveMemGuardian() } - StopActiveMemGuardian() } diff --git a/pkg/protocols/dns/dns.go b/pkg/protocols/dns/dns.go index 198bb87bd..fcfcd2cf6 100644 --- a/pkg/protocols/dns/dns.go +++ b/pkg/protocols/dns/dns.go @@ -297,3 +297,8 @@ func classToInt(class string) uint16 { } return uint16(result) } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/dns/operators.go b/pkg/protocols/dns/operators.go index 7830edfc8..fec229447 100644 --- a/pkg/protocols/dns/operators.go +++ b/pkg/protocols/dns/operators.go @@ -152,7 +152,7 @@ func traceToString(traceData *retryabledns.TraceData, withSteps bool) string { if withSteps { fmt.Fprintf(buffer, "request %d to resolver %s:\n", i, strings.Join(dnsRecord.Resolver, ",")) } - buffer.WriteString(dnsRecord.Raw) + _, _ = fmt.Fprintf(buffer, "%s\n", dnsRecord.Raw) } } return buffer.String() diff --git a/pkg/protocols/file/file.go b/pkg/protocols/file/file.go index f0e1b0d4f..ef3113c25 100644 --- a/pkg/protocols/file/file.go +++ b/pkg/protocols/file/file.go @@ -191,3 +191,8 @@ func extractMimeTypes(m []string) []string { func (request *Request) Requests() int { return 0 } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/file/request.go b/pkg/protocols/file/request.go index e19597ae5..8296dee17 100644 --- a/pkg/protocols/file/request.go +++ b/pkg/protocols/file/request.go @@ -66,8 +66,8 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, return } defer func() { - _ = fi.Close() - }() + _ = fi.Close() + }() format, stream, _ := archives.Identify(input.Context(), filePath, fi) switch { case format != nil: @@ -86,8 +86,8 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, return err } defer func() { - _ = reader.Close() - }() + _ = reader.Close() + }() event, fileMatches, err := request.processReader(reader, archiveFileName, input, file.Size(), previous) if err != nil { if errors.Is(err, errEmptyResult) { @@ -202,8 +202,8 @@ func (request *Request) processFile(filePath string, input *contextargs.Context, return nil, nil, errors.Errorf("Could not open file path %s: %s\n", filePath, err) } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() stat, err := file.Stat() if err != nil { diff --git a/pkg/protocols/headless/engine/engine.go b/pkg/protocols/headless/engine/engine.go index b425f85dd..63dbb41ef 100644 --- a/pkg/protocols/headless/engine/engine.go +++ b/pkg/protocols/headless/engine/engine.go @@ -15,15 +15,18 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" fileutil "github.com/projectdiscovery/utils/file" osutils "github.com/projectdiscovery/utils/os" + processutil "github.com/projectdiscovery/utils/process" ) // Browser is a browser structure for nuclei headless module type Browser struct { - customAgent string - tempDir string - 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 httpClientOnce *sync.Once @@ -35,6 +38,7 @@ func New(options *types.Options) (*Browser, error) { if err != nil { return nil, errors.Wrap(err, "could not create temporary directory") } + previousPIDs := processutil.FindProcesses(processutil.IsChromeProcess) chromeLauncher := launcher.New(). Leakless(false). @@ -110,6 +114,7 @@ func New(options *types.Options) (*Browser, error) { httpClientOnce: &sync.Once{}, launcher: chromeLauncher, } + engine.previousPIDs = previousPIDs return engine, nil } @@ -142,5 +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) } diff --git a/pkg/protocols/headless/engine/http_client.go b/pkg/protocols/headless/engine/http_client.go index 5ecddf700..fc8cd0a2c 100644 --- a/pkg/protocols/headless/engine/http_client.go +++ b/pkg/protocols/headless/engine/http_client.go @@ -3,6 +3,7 @@ package engine import ( "context" "crypto/tls" + "fmt" "net" "net/http" "net/http/cookiejar" @@ -19,8 +20,10 @@ import ( // newHttpClient creates a new http client for headless communication with a timeout func newHttpClient(options *types.Options) (*http.Client, error) { - dialer := protocolstate.Dialer - + dialers := protocolstate.GetDialersWithId(options.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", options.ExecutionId) + } // Set the base TLS configuration definition tlsConfig := &tls.Config{ Renegotiation: tls.RenegotiateOnceAsClient, @@ -41,15 +44,15 @@ func newHttpClient(options *types.Options) (*http.Client, error) { transport := &http.Transport{ ForceAttemptHTTP2: options.ForceAttemptHTTP2, - DialContext: dialer.Dial, + DialContext: dialers.Fastdialer.Dial, DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { if options.TlsImpersonate { - return dialer.DialTLSWithConfigImpersonate(ctx, network, addr, tlsConfig, impersonate.Random, nil) + return dialers.Fastdialer.DialTLSWithConfigImpersonate(ctx, network, addr, tlsConfig, impersonate.Random, nil) } if options.HasClientCertificates() || options.ForceAttemptHTTP2 { - return dialer.DialTLSWithConfig(ctx, network, addr, tlsConfig) + return dialers.Fastdialer.DialTLSWithConfig(ctx, network, addr, tlsConfig) } - return dialer.DialTLS(ctx, network, addr) + return dialers.Fastdialer.DialTLS(ctx, network, addr) }, MaxIdleConns: 500, MaxIdleConnsPerHost: 500, diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index 519712b21..6986f80b4 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -201,7 +201,9 @@ func (i *Instance) Run(ctx *contextargs.Context, actions []*Action, payloads map if resp, err := http.ReadResponse(bufio.NewReader(strings.NewReader(firstItem.RawResponse)), nil); err == nil { data["header"] = utils.HeadersToString(resp.Header) data["status_code"] = fmt.Sprint(resp.StatusCode) - _ = resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() } } diff --git a/pkg/protocols/headless/engine/page_actions.go b/pkg/protocols/headless/engine/page_actions.go index 492b58bb7..c051357d9 100644 --- a/pkg/protocols/headless/engine/page_actions.go +++ b/pkg/protocols/headless/engine/page_actions.go @@ -529,7 +529,7 @@ func (p *Page) Screenshot(act *Action, out ActionData) error { } // allow if targetPath is child of current working directory - if !protocolstate.IsLFAAllowed() { + if !protocolstate.IsLfaAllowed(p.options.Options) { cwd, err := os.Getwd() if err != nil { return errorutil.NewWithErr(err).Msgf("could not get current working directory") @@ -678,7 +678,7 @@ func (p *Page) WaitPageLifecycleEvent(act *Action, out ActionData, event proto.P // WaitStable waits until the page is stable func (p *Page) WaitStable(act *Action, out ActionData) error { - var dur = time.Second // default stable page duration: 1s + dur := time.Second // default stable page duration: 1s timeout, err := getTimeout(p, act) if err != nil { diff --git a/pkg/protocols/headless/engine/page_actions_test.go b/pkg/protocols/headless/engine/page_actions_test.go index 04f6d5f49..ec16b9ed7 100644 --- a/pkg/protocols/headless/engine/page_actions_test.go +++ b/pkg/protocols/headless/engine/page_actions_test.go @@ -22,6 +22,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/testutils/testheadless" "github.com/projectdiscovery/nuclei/v3/pkg/types" + envutil "github.com/projectdiscovery/utils/env" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -643,8 +644,9 @@ func testHeadlessSimpleResponse(t *testing.T, response string, actions []*Action func testHeadless(t *testing.T, actions []*Action, timeout time.Duration, handler func(w http.ResponseWriter, r *http.Request), assert func(page *Page, pageErr error, extractedData ActionData)) { t.Helper() - lfa := getBoolFromEnv("LOCAL_FILE_ACCESS", true) - rna := getBoolFromEnv("RESTRICED_LOCAL_NETWORK_ACCESS", false) + lfa := envutil.GetEnvOrDefault("LOCAL_FILE_ACCESS", true) + rna := envutil.GetEnvOrDefault("RESTRICED_LOCAL_NETWORK_ACCESS", false) + opts := &types.Options{AllowLocalFileAccess: lfa, RestrictLocalNetworkAccess: rna} _ = protocolstate.Init(opts) @@ -755,11 +757,3 @@ func TestBlockedHeadlessURLS(t *testing.T) { } } } - -func getBoolFromEnv(key string, defaultValue bool) bool { - val := os.Getenv(key) - if val == "" { - return defaultValue - } - return strings.EqualFold(val, "true") -} diff --git a/pkg/protocols/headless/engine/rules.go b/pkg/protocols/headless/engine/rules.go index cf7fd3d4f..0ff933aea 100644 --- a/pkg/protocols/headless/engine/rules.go +++ b/pkg/protocols/headless/engine/rules.go @@ -110,7 +110,7 @@ func (p *Page) routingRuleHandlerNative(e *proto.FetchRequestPaused) error { // ValidateNFailRequest validates if Local file access is enabled // and local network access is enables if not it will fail the request // that don't match the rules - if err := protocolstate.ValidateNFailRequest(p.page, e); err != nil { + if err := protocolstate.ValidateNFailRequest(p.options.Options, p.page, e); err != nil { return err } body, _ := FetchGetResponseBody(p.page, e) diff --git a/pkg/protocols/headless/headless.go b/pkg/protocols/headless/headless.go index 373880f1a..dc27d6a57 100644 --- a/pkg/protocols/headless/headless.go +++ b/pkg/protocols/headless/headless.go @@ -170,3 +170,8 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { func (request *Request) Requests() int { return 1 } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/headless/request.go b/pkg/protocols/headless/request.go index 5e508c02b..7518cbc6c 100644 --- a/pkg/protocols/headless/request.go +++ b/pkg/protocols/headless/request.go @@ -164,11 +164,11 @@ func (request *Request) executeRequestWithPayloads(input *contextargs.Context, p if reqLog[value] != "" { _, _ = fmt.Fprintf(reqBuilder, "\tnavigate => %v\n", reqLog[value]) } else { - fmt.Fprintf(reqBuilder, "%v not found in %v\n", value, reqLog) + _, _ = fmt.Fprintf(reqBuilder, "%v not found in %v\n", value, reqLog) } } else { actStepStr := act.String() - reqBuilder.WriteString("\t" + actStepStr + "\n") + _, _ = fmt.Fprintf(reqBuilder, "\t%s\n", actStepStr) } } gologger.Debug().Msg(reqBuilder.String()) diff --git a/pkg/protocols/http/cluster.go b/pkg/protocols/http/cluster.go index d0824ff03..a13d7fc81 100644 --- a/pkg/protocols/http/cluster.go +++ b/pkg/protocols/http/cluster.go @@ -17,5 +17,6 @@ func (request *Request) TmplClusterKey() uint64 { // IsClusterable returns true if the request is eligible to be clustered. func (request *Request) IsClusterable() bool { - return len(request.Payloads) <= 0 && len(request.Fuzzing) <= 0 && len(request.Raw) <= 0 && len(request.Body) <= 0 && !request.Unsafe && !request.NeedsRequestCondition() && request.Name == "" + //nolint + return !(len(request.Payloads) > 0 || len(request.Fuzzing) > 0 || len(request.Raw) > 0 || len(request.Body) > 0 || request.Unsafe || request.NeedsRequestCondition() || request.Name != "") } diff --git a/pkg/protocols/http/http.go b/pkg/protocols/http/http.go index 7a45fcd0d..ae3f3f471 100644 --- a/pkg/protocols/http/http.go +++ b/pkg/protocols/http/http.go @@ -539,3 +539,8 @@ const ( func init() { stats.NewEntry(SetThreadToCountZero, "Setting thread count to 0 for %d templates, dynamic extractors are not supported with payloads yet") } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/http/httpclientpool/clientpool.go b/pkg/protocols/http/httpclientpool/clientpool.go index 5c1a91cb5..940ac3886 100644 --- a/pkg/protocols/http/httpclientpool/clientpool.go +++ b/pkg/protocols/http/httpclientpool/clientpool.go @@ -25,36 +25,19 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types/scanstrategy" "github.com/projectdiscovery/rawhttp" "github.com/projectdiscovery/retryablehttp-go" - mapsutil "github.com/projectdiscovery/utils/maps" urlutil "github.com/projectdiscovery/utils/url" ) var ( - rawHttpClient *rawhttp.Client - rawHttpClientOnce sync.Once forceMaxRedirects int - normalClient *retryablehttp.Client - clientPool *mapsutil.SyncLockMap[string, *retryablehttp.Client] ) // Init initializes the clientpool implementation func Init(options *types.Options) error { - // Don't create clients if already created in the past. - if normalClient != nil { - return nil - } if options.ShouldFollowHTTPRedirects() { forceMaxRedirects = options.MaxRedirects } - clientPool = &mapsutil.SyncLockMap[string, *retryablehttp.Client]{ - Map: make(mapsutil.Map[string, *retryablehttp.Client]), - } - client, err := wrappedGet(options, &Configuration{}) - if err != nil { - return err - } - normalClient = client return nil } @@ -158,26 +141,42 @@ func (c *Configuration) HasStandardOptions() bool { // GetRawHTTP returns the rawhttp request client func GetRawHTTP(options *protocols.ExecutorOptions) *rawhttp.Client { - rawHttpClientOnce.Do(func() { - rawHttpOptions := rawhttp.DefaultOptions - if options.Options.AliveHttpProxy != "" { - rawHttpOptions.Proxy = options.Options.AliveHttpProxy - } else if options.Options.AliveSocksProxy != "" { - rawHttpOptions.Proxy = options.Options.AliveSocksProxy - } else if protocolstate.Dialer != nil { - rawHttpOptions.FastDialer = protocolstate.Dialer - } - rawHttpOptions.Timeout = options.Options.GetTimeouts().HttpTimeout - rawHttpClient = rawhttp.NewClient(rawHttpOptions) - }) - return rawHttpClient + dialers := protocolstate.GetDialersWithId(options.Options.ExecutionId) + if dialers == nil { + panic("dialers not initialized for execution id: " + options.Options.ExecutionId) + } + + // Lock the dialers to avoid a race when setting RawHTTPClient + dialers.Lock() + defer dialers.Unlock() + + if dialers.RawHTTPClient != nil { + return dialers.RawHTTPClient + } + + rawHttpOptions := rawhttp.DefaultOptions + if options.Options.AliveHttpProxy != "" { + rawHttpOptions.Proxy = options.Options.AliveHttpProxy + } else if options.Options.AliveSocksProxy != "" { + rawHttpOptions.Proxy = options.Options.AliveSocksProxy + } else if dialers.Fastdialer != nil { + rawHttpOptions.FastDialer = dialers.Fastdialer + } + rawHttpOptions.Timeout = options.Options.GetTimeouts().HttpTimeout + dialers.RawHTTPClient = rawhttp.NewClient(rawHttpOptions) + return dialers.RawHTTPClient } // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration) (*retryablehttp.Client, error) { if configuration.HasStandardOptions() { - return normalClient, nil + dialers := protocolstate.GetDialersWithId(options.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", options.ExecutionId) + } + return dialers.DefaultHTTPClient, nil } + return wrappedGet(options, configuration) } @@ -185,8 +184,13 @@ func Get(options *types.Options, configuration *Configuration) (*retryablehttp.C func wrappedGet(options *types.Options, configuration *Configuration) (*retryablehttp.Client, error) { var err error + dialers := protocolstate.GetDialersWithId(options.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", options.ExecutionId) + } + hash := configuration.Hash() - if client, ok := clientPool.Get(hash); ok { + if client, ok := dialers.HTTPClientPool.Get(hash); ok { return client, nil } @@ -263,15 +267,15 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl transport := &http.Transport{ ForceAttemptHTTP2: options.ForceAttemptHTTP2, - DialContext: protocolstate.GetDialer().Dial, + DialContext: dialers.Fastdialer.Dial, DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { if options.TlsImpersonate { - return protocolstate.Dialer.DialTLSWithConfigImpersonate(ctx, network, addr, tlsConfig, impersonate.Random, nil) + return dialers.Fastdialer.DialTLSWithConfigImpersonate(ctx, network, addr, tlsConfig, impersonate.Random, nil) } if options.HasClientCertificates() || options.ForceAttemptHTTP2 { - return protocolstate.Dialer.DialTLSWithConfig(ctx, network, addr, tlsConfig) + return dialers.Fastdialer.DialTLSWithConfig(ctx, network, addr, tlsConfig) } - return protocolstate.GetDialer().DialTLS(ctx, network, addr) + return dialers.Fastdialer.DialTLS(ctx, network, addr) }, MaxIdleConns: maxIdleConns, MaxIdleConnsPerHost: maxIdleConnsPerHost, @@ -346,7 +350,7 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl // Only add to client pool if we don't have a cookie jar in place. if jar == nil { - if err := clientPool.Set(hash, client); err != nil { + if err := dialers.HTTPClientPool.Set(hash, client); err != nil { return nil, err } } diff --git a/pkg/protocols/http/race/syncedreadcloser.go b/pkg/protocols/http/race/syncedreadcloser.go index 554bedc48..9aadf1c32 100644 --- a/pkg/protocols/http/race/syncedreadcloser.go +++ b/pkg/protocols/http/race/syncedreadcloser.go @@ -26,7 +26,9 @@ func NewSyncedReadCloser(r io.ReadCloser) *SyncedReadCloser { if err != nil { return nil } - _ = r.Close() + defer func() { + _ = r.Close() + }() s.length = int64(len(s.data)) s.openGate = make(chan struct{}) s.enableBlocking = true diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index a610534d7..fc181d1c5 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -742,7 +742,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ }) } else { //** For Normal requests **// - hostname = generatedRequest.request.URL.Host + hostname = generatedRequest.request.Host formedURL = generatedRequest.request.String() // if nuclei-project is available check if the request was already sent previously if request.options.ProjectFile != nil { @@ -818,6 +818,11 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ } } + dialers := protocolstate.GetDialersWithId(request.options.Options.ExecutionId) + if dialers == nil { + return fmt.Errorf("dialers not found for execution id %s", request.options.Options.ExecutionId) + } + if err != nil { // rawhttp doesn't support draining response bodies. if resp != nil && resp.Body != nil && generatedRequest.rawRequest == nil && !generatedRequest.original.Pipeline { @@ -838,7 +843,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ if input.MetaInput.CustomIP != "" { outputEvent["ip"] = input.MetaInput.CustomIP } else { - outputEvent["ip"] = request.dialer.GetDialedIP(hostname) + outputEvent["ip"] = dialers.Fastdialer.GetDialedIP(hostname) // try getting cname request.addCNameIfAvailable(hostname, outputEvent) } @@ -958,7 +963,7 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ if input.MetaInput.CustomIP != "" { outputEvent["ip"] = input.MetaInput.CustomIP } else { - dialer := protocolstate.GetDialer() + dialer := dialers.Fastdialer if dialer != nil { outputEvent["ip"] = dialer.GetDialedIP(hostname) } diff --git a/pkg/protocols/http/request_annotations_test.go b/pkg/protocols/http/request_annotations_test.go index bbc376f8a..778a0cb72 100644 --- a/pkg/protocols/http/request_annotations_test.go +++ b/pkg/protocols/http/request_annotations_test.go @@ -23,7 +23,7 @@ func TestRequestParseAnnotationsSNI(t *testing.T) { overrides, modified := req.parseAnnotations(rawRequest, httpReq) require.True(t, modified, "could not apply request annotations") require.Equal(t, "github.com", overrides.request.TLS.ServerName) - require.Equal(t, "example.com", overrides.request.Hostname()) + require.Equal(t, "example.com", overrides.request.Host) }) t.Run("non-compliant-SNI-value", func(t *testing.T) { req := &Request{connConfiguration: &httpclientpool.Configuration{}} @@ -37,7 +37,7 @@ func TestRequestParseAnnotationsSNI(t *testing.T) { overrides, modified := req.parseAnnotations(rawRequest, httpReq) require.True(t, modified, "could not apply request annotations") require.Equal(t, "${jndi:ldap://${hostName}.test.com}", overrides.request.TLS.ServerName) - require.Equal(t, "example.com", overrides.request.Hostname()) + require.Equal(t, "example.com", overrides.request.Host) }) } diff --git a/pkg/protocols/http/request_fuzz.go b/pkg/protocols/http/request_fuzz.go index c800b6aff..045dec332 100644 --- a/pkg/protocols/http/request_fuzz.go +++ b/pkg/protocols/http/request_fuzz.go @@ -311,7 +311,7 @@ func (request *Request) filterDataMap(input *contextargs.Context) map[string]int if strings.EqualFold(k, "content_type") { m["content_type"] = v } - fmt.Fprintf(sb, "%s: %s\n", k, v) + _, _ = fmt.Fprintf(sb, "%s: %s\n", k, v) return true }) m["header"] = sb.String() diff --git a/pkg/protocols/http/request_test.go b/pkg/protocols/http/request_test.go index 0cdabba91..a6314ae5a 100644 --- a/pkg/protocols/http/request_test.go +++ b/pkg/protocols/http/request_test.go @@ -61,10 +61,10 @@ func TestHTTPExtractMultipleReuse(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/robots.txt": - _, _ = w.Write([]byte(`User-agent: Googlebot + _, _ = fmt.Fprintf(w, `User-agent: Googlebot Disallow: /a Disallow: /b -Disallow: /c`)) +Disallow: /c`) default: _, _ = fmt.Fprintf(w, `match %v`, r.URL.Path) } diff --git a/pkg/protocols/http/signerpool/signerpool.go b/pkg/protocols/http/signerpool/signerpool.go index f4fecf763..c7ca1844e 100644 --- a/pkg/protocols/http/signerpool/signerpool.go +++ b/pkg/protocols/http/signerpool/signerpool.go @@ -11,13 +11,17 @@ import ( ) var ( - poolMutex *sync.RWMutex + poolMutex sync.RWMutex clientPool map[string]signer.Signer ) // Init initializes the clientpool implementation func Init(options *types.Options) error { - poolMutex = &sync.RWMutex{} + poolMutex.Lock() + defer poolMutex.Unlock() + if clientPool != nil { + return nil // already initialized + } clientPool = make(map[string]signer.Signer) return nil } diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index e8b9c0b38..0d4a41e03 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -9,9 +9,9 @@ import ( "sync/atomic" "time" + "github.com/Mzack9999/goja" "github.com/alecthomas/chroma/quick" "github.com/ditashi/jsbeautifier-go/jsbeautifier" - "github.com/dop251/goja" "github.com/pkg/errors" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/js/compiler" @@ -151,6 +151,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { } opts := &compiler.ExecuteOptions{ + ExecutionId: request.options.Options.ExecutionId, TimeoutVariants: request.options.Options.GetTimeouts(), Source: &request.Init, Context: context.Background(), @@ -357,6 +358,7 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV result, err := request.options.JsCompiler.ExecuteWithOptions(request.preConditionCompiled, argsCopy, &compiler.ExecuteOptions{ + ExecutionId: requestOptions.Options.ExecutionId, TimeoutVariants: requestOptions.Options.GetTimeouts(), Source: &request.PreCondition, Context: target.Context(), }) @@ -530,6 +532,7 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte results, err := request.options.JsCompiler.ExecuteWithOptions(request.scriptCompiled, argsCopy, &compiler.ExecuteOptions{ + ExecutionId: requestOptions.Options.ExecutionId, TimeoutVariants: requestOptions.Options.GetTimeouts(), Source: &request.Code, Context: input.Context(), @@ -611,6 +614,11 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte // generateEventData generates event data for the request func (request *Request) generateEventData(input *contextargs.Context, values map[string]interface{}, matched string) map[string]interface{} { + dialers := protocolstate.GetDialersWithId(request.options.Options.ExecutionId) + if dialers == nil { + panic(fmt.Sprintf("dialers not initialized for %s", request.options.Options.ExecutionId)) + } + data := make(map[string]interface{}) for k, v := range values { data[k] = v @@ -643,7 +651,7 @@ func (request *Request) generateEventData(input *contextargs.Context, values map } } } - data["ip"] = protocolstate.Dialer.GetDialedIP(hostname) + data["ip"] = dialers.Fastdialer.GetDialedIP(hostname) // if input itself was an ip, use it if iputil.IsIP(hostname) { data["ip"] = hostname @@ -651,7 +659,7 @@ func (request *Request) generateEventData(input *contextargs.Context, values map // if ip is not found,this is because ssh and other protocols do not use fastdialer // although its not perfect due to its use case dial and get ip - dnsData, err := protocolstate.Dialer.GetDNSData(hostname) + dnsData, err := dialers.Fastdialer.GetDNSData(hostname) if err == nil { for _, v := range dnsData.A { data["ip"] = v @@ -816,3 +824,8 @@ func prettyPrint(templateId string, buff string) { } gologger.Debug().Msgf(" [%v] Javascript Code:\n\n%v\n\n", templateId, strings.Join(final, "\n")) } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/javascript/js_test.go b/pkg/protocols/javascript/js_test.go index efb78ef6e..bdfc54d22 100644 --- a/pkg/protocols/javascript/js_test.go +++ b/pkg/protocols/javascript/js_test.go @@ -23,7 +23,7 @@ var ( "testcases/redis-pass-brute.yaml", "testcases/ssh-server-fingerprint.yaml", } - executerOpts protocols.ExecutorOptions + executerOpts *protocols.ExecutorOptions ) func setup() { @@ -31,7 +31,7 @@ func setup() { testutils.Init(options) progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0) - executerOpts = protocols.ExecutorOptions{ + executerOpts = &protocols.ExecutorOptions{ Output: testutils.NewMockOutputWriter(options.OmitTemplate), Options: options, Progress: progressImpl, @@ -42,7 +42,7 @@ func setup() { RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second), Parser: templates.NewParser(), } - workflowLoader, err := workflow.NewLoader(&executerOpts) + workflowLoader, err := workflow.NewLoader(executerOpts) if err != nil { log.Fatalf("Could not create workflow loader: %s\n", err) } diff --git a/pkg/protocols/network/network.go b/pkg/protocols/network/network.go index 7aba6244a..be3c85cd6 100644 --- a/pkg/protocols/network/network.go +++ b/pkg/protocols/network/network.go @@ -261,3 +261,12 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { func (request *Request) Requests() int { return len(request.Address) } + +func (request *Request) SetDialer(dialer *fastdialer.Dialer) { + request.dialer = dialer +} + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/network/networkclientpool/clientpool.go b/pkg/protocols/network/networkclientpool/clientpool.go index 6293a931e..7fc4203cb 100644 --- a/pkg/protocols/network/networkclientpool/clientpool.go +++ b/pkg/protocols/network/networkclientpool/clientpool.go @@ -1,22 +1,15 @@ package networkclientpool import ( + "fmt" + "github.com/projectdiscovery/fastdialer/fastdialer" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/types" ) -var ( - normalClient *fastdialer.Dialer -) - // Init initializes the clientpool implementation func Init(options *types.Options) error { - // Don't create clients if already created in the past. - if normalClient != nil { - return nil - } - normalClient = protocolstate.Dialer return nil } @@ -32,10 +25,12 @@ func (c *Configuration) Hash() string { // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration /*TODO review unused parameters*/) (*fastdialer.Dialer, error) { - if configuration != nil && configuration.CustomDialer != nil { return configuration.CustomDialer, nil } - - return normalClient, nil + dialers := protocolstate.GetDialersWithId(options.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", options.ExecutionId) + } + return dialers.Fastdialer, nil } diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index 77b49c6bd..189724033 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -303,8 +303,8 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac return errors.Wrap(err, "could not connect to server") } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() _ = conn.SetDeadline(time.Now().Add(time.Duration(request.options.Options.Timeout) * time.Second)) var interactshURLs []string diff --git a/pkg/protocols/offlinehttp/request.go b/pkg/protocols/offlinehttp/request.go index 8849b44ab..fa2179f88 100644 --- a/pkg/protocols/offlinehttp/request.go +++ b/pkg/protocols/offlinehttp/request.go @@ -58,8 +58,8 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, metadata, return } defer func() { - _ = file.Close() - }() + _ = file.Close() + }() stat, err := file.Stat() if err != nil { @@ -139,3 +139,8 @@ func getURLFromRequest(req *http.Request) string { } return fmt.Sprintf("%s://%s%s", req.URL.Scheme, req.Host, req.URL.Path) } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options = opts +} diff --git a/pkg/protocols/protocols.go b/pkg/protocols/protocols.go index 6b5c089be..30443eee6 100644 --- a/pkg/protocols/protocols.go +++ b/pkg/protocols/protocols.go @@ -3,9 +3,11 @@ package protocols import ( "context" "encoding/base64" + "sync" "sync/atomic" "github.com/projectdiscovery/fastdialer/fastdialer" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/ratelimit" mapsutil "github.com/projectdiscovery/utils/maps" stringsutil "github.com/projectdiscovery/utils/strings" @@ -133,19 +135,29 @@ type ExecutorOptions struct { ExportReqURLPattern bool // GlobalMatchers is the storage for global matchers with http passive templates GlobalMatchers *globalmatchers.Storage + // Logger is the shared logging instance + Logger *gologger.Logger // CustomFastdialer is a fastdialer dialer instance CustomFastdialer *fastdialer.Dialer + + m sync.Mutex } // todo: centralizing components is not feasible with current clogged architecture // a possible approach could be an internal event bus with pub-subs? This would be less invasive than // reworking dep injection from scratch -func (eo *ExecutorOptions) RateLimitTake() { - if eo.RateLimiter.GetLimit() != uint(eo.Options.RateLimit) { - eo.RateLimiter.SetLimit(uint(eo.Options.RateLimit)) - eo.RateLimiter.SetDuration(eo.Options.RateLimitDuration) +func (e *ExecutorOptions) RateLimitTake() { + // The code below can race and there isn't a great way to fix this without adding an idempotent + // function to the rate limiter implementation. For now, stick with whatever rate is already set. + /* + if e.RateLimiter.GetLimit() != uint(e.Options.RateLimit) { + e.RateLimiter.SetLimit(uint(e.Options.RateLimit)) + e.RateLimiter.SetDuration(e.Options.RateLimitDuration) + } + */ + if e.RateLimiter != nil { + e.RateLimiter.Take() } - eo.RateLimiter.Take() } // GetThreadsForPayloadRequests returns the number of threads to use as default for @@ -246,8 +258,46 @@ func (e *ExecutorOptions) AddTemplateVar(input *contextargs.MetaInput, templateT } // Copy returns a copy of the executeroptions structure -func (e ExecutorOptions) Copy() ExecutorOptions { - copy := e +func (e *ExecutorOptions) Copy() *ExecutorOptions { + copy := &ExecutorOptions{ + TemplateID: e.TemplateID, + TemplatePath: e.TemplatePath, + TemplateInfo: e.TemplateInfo, + TemplateVerifier: e.TemplateVerifier, + RawTemplate: e.RawTemplate, + Output: e.Output, + Options: e.Options, + IssuesClient: e.IssuesClient, + Progress: e.Progress, + RateLimiter: e.RateLimiter, + Catalog: e.Catalog, + ProjectFile: e.ProjectFile, + Browser: e.Browser, + Interactsh: e.Interactsh, + HostErrorsCache: e.HostErrorsCache, + StopAtFirstMatch: e.StopAtFirstMatch, + Variables: e.Variables, + Constants: e.Constants, + ExcludeMatchers: e.ExcludeMatchers, + InputHelper: e.InputHelper, + FuzzParamsFrequency: e.FuzzParamsFrequency, + FuzzStatsDB: e.FuzzStatsDB, + Operators: e.Operators, + DoNotCache: e.DoNotCache, + Colorizer: e.Colorizer, + WorkflowLoader: e.WorkflowLoader, + ResumeCfg: e.ResumeCfg, + ProtocolType: e.ProtocolType, + Flow: e.Flow, + IsMultiProtocol: e.IsMultiProtocol, + JsCompiler: e.JsCompiler, + AuthProvider: e.AuthProvider, + TemporaryDirectory: e.TemporaryDirectory, + Parser: e.Parser, + ExportReqURLPattern: e.ExportReqURLPattern, + GlobalMatchers: e.GlobalMatchers, + Logger: e.Logger, + } copy.CreateTemplateCtxStore() return copy } @@ -386,3 +436,22 @@ func (e *ExecutorOptions) EncodeTemplate() string { } return "" } + +// ApplyNewEngineOptions updates an existing ExecutorOptions with options from a new engine. This +// handles things like the ExecutionID that need to be updated. +func (e *ExecutorOptions) ApplyNewEngineOptions(n *ExecutorOptions) { + // TODO: cached code|headless templates have nil ExecuterOptions if -code or -headless are not enabled + if e == nil || n == nil || n.Options == nil { + return + } + execID := n.Options.GetExecutionID() + e.SetExecutionID(execID) +} + +// ApplyNewEngineOptions updates an existing ExecutorOptions with options from a new engine. This +// handles things like the ExecutionID that need to be updated. +func (e *ExecutorOptions) SetExecutionID(executorId string) { + e.m.Lock() + defer e.m.Unlock() + e.Options.SetExecutionID(executorId) +} diff --git a/pkg/protocols/ssl/ssl.go b/pkg/protocols/ssl/ssl.go index cc73930e9..8764d6f5f 100644 --- a/pkg/protocols/ssl/ssl.go +++ b/pkg/protocols/ssl/ssl.go @@ -108,7 +108,8 @@ func (request *Request) TmplClusterKey() uint64 { } func (request *Request) IsClusterable() bool { - return len(request.CipherSuites) <= 0 && request.MinVersion == "" && request.MaxVersion == "" + // nolint + return !(len(request.CipherSuites) > 0 || request.MinVersion != "" || request.MaxVersion != "") } // Compile compiles the request generators preparing any requests possible. @@ -437,3 +438,8 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent } return data } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/websocket/websocket.go b/pkg/protocols/websocket/websocket.go index e17e5512a..175002e53 100644 --- a/pkg/protocols/websocket/websocket.go +++ b/pkg/protocols/websocket/websocket.go @@ -236,8 +236,8 @@ func (request *Request) executeRequestWithPayloads(target *contextargs.Context, return errors.Wrap(err, "could not connect to server") } defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() responseBuilder := &strings.Builder{} if readBuffer != nil { @@ -428,3 +428,8 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent func (request *Request) Type() templateTypes.ProtocolType { return templateTypes.WebsocketProtocol } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/protocols/whois/rdapclientpool/clientpool.go b/pkg/protocols/whois/rdapclientpool/clientpool.go index cb393a505..81da1c578 100644 --- a/pkg/protocols/whois/rdapclientpool/clientpool.go +++ b/pkg/protocols/whois/rdapclientpool/clientpool.go @@ -1,15 +1,21 @@ package rdapclientpool import ( + "sync" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/rdap" ) var normalClient *rdap.Client +var m sync.Mutex // Init initializes the client pool implementation func Init(options *types.Options) error { + m.Lock() + defer m.Unlock() + // Don't create clients if already created in the past. if normalClient != nil { return nil @@ -34,5 +40,7 @@ func (c *Configuration) Hash() string { // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration) (*rdap.Client, error) { + m.Lock() + defer m.Unlock() return normalClient, nil } diff --git a/pkg/protocols/whois/whois.go b/pkg/protocols/whois/whois.go index 91d0edcf8..60f41719a 100644 --- a/pkg/protocols/whois/whois.go +++ b/pkg/protocols/whois/whois.go @@ -196,3 +196,8 @@ func (request *Request) MakeResultEventItem(wrapped *output.InternalWrappedEvent func (request *Request) Type() templateTypes.ProtocolType { return templateTypes.WHOISProtocol } + +// UpdateOptions replaces this request's options with a new copy +func (r *Request) UpdateOptions(opts *protocols.ExecutorOptions) { + r.options.ApplyNewEngineOptions(opts) +} diff --git a/pkg/reporting/exporters/es/elasticsearch.go b/pkg/reporting/exporters/es/elasticsearch.go index 4a1cc7e7c..dd1d0aa4e 100644 --- a/pkg/reporting/exporters/es/elasticsearch.go +++ b/pkg/reporting/exporters/es/elasticsearch.go @@ -37,7 +37,8 @@ type Options struct { // IndexName is the name of the elasticsearch index IndexName string `yaml:"index-name" validate:"required"` - HttpClient *retryablehttp.Client `yaml:"-"` + HttpClient *retryablehttp.Client `yaml:"-"` + ExecutionId string `yaml:"-"` } type data struct { @@ -56,6 +57,11 @@ type Exporter struct { func New(option *Options) (*Exporter, error) { var ei *Exporter + dialers := protocolstate.GetDialersWithId(option.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", option.ExecutionId) + } + var client *http.Client if option.HttpClient != nil { client = option.HttpClient.HTTPClient @@ -65,8 +71,8 @@ func New(option *Options) (*Exporter, error) { Transport: &http.Transport{ MaxIdleConns: 10, MaxIdleConnsPerHost: 10, - DialContext: protocolstate.Dialer.Dial, - DialTLSContext: protocolstate.Dialer.DialTLS, + DialContext: dialers.Fastdialer.Dial, + DialTLSContext: dialers.Fastdialer.DialTLS, TLSClientConfig: &tls.Config{InsecureSkipVerify: option.SSLVerification}, }, } @@ -132,8 +138,8 @@ func (exporter *Exporter) Export(event *output.ResultEvent) error { return err } defer func() { - _ = res.Body.Close() - }() + _ = res.Body.Close() + }() b, err = io.ReadAll(res.Body) if err != nil { diff --git a/pkg/reporting/exporters/splunk/splunkhec.go b/pkg/reporting/exporters/splunk/splunkhec.go index ef9c7159d..01c5ed321 100644 --- a/pkg/reporting/exporters/splunk/splunkhec.go +++ b/pkg/reporting/exporters/splunk/splunkhec.go @@ -30,7 +30,8 @@ type Options struct { Token string `yaml:"token" validate:"required"` IndexName string `yaml:"index-name" validate:"required"` - HttpClient *retryablehttp.Client `yaml:"-"` + HttpClient *retryablehttp.Client `yaml:"-"` + ExecutionId string `yaml:"-"` } type data struct { @@ -48,6 +49,11 @@ type Exporter struct { func New(option *Options) (*Exporter, error) { var ei *Exporter + dialers := protocolstate.GetDialersWithId(option.ExecutionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", option.ExecutionId) + } + var client *http.Client if option.HttpClient != nil { client = option.HttpClient.HTTPClient @@ -57,8 +63,8 @@ func New(option *Options) (*Exporter, error) { Transport: &http.Transport{ MaxIdleConns: 10, MaxIdleConnsPerHost: 10, - DialContext: protocolstate.Dialer.Dial, - DialTLSContext: protocolstate.Dialer.DialTLS, + DialContext: dialers.Fastdialer.Dial, + DialTLSContext: dialers.Fastdialer.DialTLS, TLSClientConfig: &tls.Config{InsecureSkipVerify: option.SSLVerification}, }, } diff --git a/pkg/reporting/options.go b/pkg/reporting/options.go index bda9b6c28..bbee7b207 100644 --- a/pkg/reporting/options.go +++ b/pkg/reporting/options.go @@ -50,4 +50,6 @@ type Options struct { HttpClient *retryablehttp.Client `yaml:"-"` OmitRaw bool `yaml:"-"` + + ExecutionId string `yaml:"-"` } diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index a759ab282..100f35743 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -154,6 +154,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) { } if options.ElasticsearchExporter != nil { options.ElasticsearchExporter.HttpClient = options.HttpClient + options.ElasticsearchExporter.ExecutionId = options.ExecutionId exporter, err := es.New(options.ElasticsearchExporter) if err != nil { return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) @@ -162,6 +163,7 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) { } if options.SplunkExporter != nil { options.SplunkExporter.HttpClient = options.HttpClient + options.SplunkExporter.ExecutionId = options.ExecutionId exporter, err := splunk.New(options.SplunkExporter) if err != nil { return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) @@ -228,8 +230,8 @@ func CreateConfigIfNotExists() error { return errorutil.NewWithErr(err).Msgf("could not create config file") } defer func() { - _ = reportingFile.Close() - }() + _ = reportingFile.Close() + }() err = yaml.NewEncoder(reportingFile).Encode(options) return err diff --git a/pkg/reporting/trackers/linear/linear.go b/pkg/reporting/trackers/linear/linear.go index 24b464f33..243baefe5 100644 --- a/pkg/reporting/trackers/linear/linear.go +++ b/pkg/reporting/trackers/linear/linear.go @@ -385,8 +385,8 @@ func (i *Integration) doGraphqlRequest(ctx context.Context, query string, v any, return err } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("non-200 OK status code: %v body: %q", resp.Status, body) diff --git a/pkg/scan/charts/charts.go b/pkg/scan/charts/charts.go index e651b7152..fde60422c 100644 --- a/pkg/scan/charts/charts.go +++ b/pkg/scan/charts/charts.go @@ -55,8 +55,8 @@ func NewScanEventsCharts(eventsDir string) (*ScanEventsCharts, error) { return nil, err } defer func() { - _ = f.Close() - }() + _ = f.Close() + }() data := []events.ScanEvent{} dec := json.NewDecoder(f) diff --git a/pkg/scan/charts/echarts.go b/pkg/scan/charts/echarts.go index 719292196..effc95ca0 100644 --- a/pkg/scan/charts/echarts.go +++ b/pkg/scan/charts/echarts.go @@ -31,8 +31,8 @@ func (s *ScanEventsCharts) GenerateHTML(filePath string) error { return err } defer func() { - _ = output.Close() - }() + _ = output.Close() + }() return page.Render(output) } @@ -71,7 +71,7 @@ func (s *ScanEventsCharts) totalRequestsOverTime(c echo.Context) *charts.Line { }), ) - var startTime = time.Now() + startTime := time.Now() var endTime time.Time for _, event := range s.data { @@ -137,7 +137,7 @@ func (s *ScanEventsCharts) topSlowTemplates(c echo.Context) *charts.Kline { }), ) ids := map[string][]int64{} - var startTime = time.Now() + startTime := time.Now() for _, event := range s.data { if event.Time.Before(startTime) { startTime = event.Time diff --git a/pkg/templates/cluster.go b/pkg/templates/cluster.go index 8008eb0e5..46a031534 100644 --- a/pkg/templates/cluster.go +++ b/pkg/templates/cluster.go @@ -117,7 +117,7 @@ func ClusterID(templates []*Template) string { return cryptoutil.SHA256Sum(ids) } -func ClusterTemplates(templatesList []*Template, options protocols.ExecutorOptions) ([]*Template, int) { +func ClusterTemplates(templatesList []*Template, options *protocols.ExecutorOptions) ([]*Template, int) { if options.Options.OfflineHTTP || options.Options.DisableClustering { return templatesList, 0 } @@ -146,7 +146,7 @@ func ClusterTemplates(templatesList []*Template, options protocols.ExecutorOptio RequestsDNS: cluster[0].RequestsDNS, RequestsHTTP: cluster[0].RequestsHTTP, RequestsSSL: cluster[0].RequestsSSL, - Executer: NewClusterExecuter(cluster, &executerOpts), + Executer: NewClusterExecuter(cluster, executerOpts), TotalRequests: len(cluster[0].RequestsHTTP) + len(cluster[0].RequestsDNS), }) clusterCount += len(cluster) diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index ce51a5ccf..a0d99a768 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -49,14 +49,78 @@ func init() { // Parse parses a yaml request template file // TODO make sure reading from the disk the template parsing happens once: see parsers.ParseTemplate vs templates.Parse -func Parse(filePath string, preprocessor Preprocessor, options protocols.ExecutorOptions) (*Template, error) { +func Parse(filePath string, preprocessor Preprocessor, options *protocols.ExecutorOptions) (*Template, error) { parser, ok := options.Parser.(*Parser) if !ok { panic("not a parser") } if !options.DoNotCache { - if value, _, err := parser.compiledTemplatesCache.Has(filePath); value != nil { - return value, err + if value, _, _ := parser.compiledTemplatesCache.Has(filePath); value != nil { + // Update the template to use the current options for the calling engine + // TODO: This may be require additional work for robustness + t := *value + t.Options.ApplyNewEngineOptions(options) + if t.CompiledWorkflow != nil { + t.CompiledWorkflow.Options.ApplyNewEngineOptions(options) + for _, w := range t.CompiledWorkflow.Workflows { + for _, ex := range w.Executers { + ex.Options.ApplyNewEngineOptions(options) + } + } + } + for _, r := range t.RequestsDNS { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsHTTP { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsCode { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsFile { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsHeadless { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsNetwork { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsJavascript { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsSSL { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsWHOIS { + r.UpdateOptions(t.Options) + } + for _, r := range t.RequestsWebsocket { + r.UpdateOptions(t.Options) + } + template := t + + if template.isGlobalMatchersEnabled() { + item := &globalmatchers.Item{ + TemplateID: template.ID, + TemplatePath: filePath, + TemplateInfo: template.Info, + } + for _, request := range template.RequestsHTTP { + item.Operators = append(item.Operators, request.CompiledOperators) + } + options.GlobalMatchers.AddOperator(item) + return nil, nil + } + // Compile the workflow request + if len(template.Workflows) > 0 { + compiled := &template.Workflow + compileWorkflow(filePath, preprocessor, options, compiled, options.WorkflowLoader) + template.CompiledWorkflow = compiled + template.CompiledWorkflow.Options = options + } + + return &template, nil } } @@ -76,11 +140,13 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Executo } defer func() { - _ = reader.Close() - }() + _ = reader.Close() + }() + // Make a copy of the options for this template + options = options.Copy() options.TemplatePath = filePath - template, err := ParseTemplateFromReader(reader, preprocessor, options.Copy()) + template, err := ParseTemplateFromReader(reader, preprocessor, options) if err != nil { return nil, err } @@ -100,9 +166,9 @@ func Parse(filePath string, preprocessor Preprocessor, options protocols.Executo if len(template.Workflows) > 0 { compiled := &template.Workflow - compileWorkflow(filePath, preprocessor, &options, compiled, options.WorkflowLoader) + compileWorkflow(filePath, preprocessor, options, compiled, options.WorkflowLoader) template.CompiledWorkflow = compiled - template.CompiledWorkflow.Options = &options + template.CompiledWorkflow.Options = options } template.Path = filePath if !options.DoNotCache { @@ -284,7 +350,7 @@ mainLoop: // ParseTemplateFromReader reads the template from reader // returns the parsed template -func ParseTemplateFromReader(reader io.Reader, preprocessor Preprocessor, options protocols.ExecutorOptions) (*Template, error) { +func ParseTemplateFromReader(reader io.Reader, preprocessor Preprocessor, options *protocols.ExecutorOptions) (*Template, error) { data, err := io.ReadAll(reader) if err != nil { return nil, err @@ -355,7 +421,10 @@ func ParseTemplateFromReader(reader io.Reader, preprocessor Preprocessor, option } // this method does not include any kind of preprocessing -func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, error) { +func parseTemplate(data []byte, srcOptions *protocols.ExecutorOptions) (*Template, error) { + // Create a copy of the options specifically for this template + options := srcOptions.Copy() + template := &Template{} var err error switch config.GetTemplateFormatFromExt(template.Path) { @@ -418,10 +487,10 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e // initialize the js compiler if missing if options.JsCompiler == nil { - options.JsCompiler = GetJsCompiler() + options.JsCompiler = GetJsCompiler() // this is a singleton } - template.Options = &options + template.Options = options // If no requests, and it is also not a workflow, return error. if template.Requests() == 0 { return nil, fmt.Errorf("no requests defined for %s", template.ID) @@ -462,7 +531,8 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e } } options.TemplateVerifier = template.TemplateVerifier - if !template.Verified || verifier.Identifier() != "projectdiscovery/nuclei-templates" { + //nolint + if !(template.Verified && verifier.Identifier() == "projectdiscovery/nuclei-templates") { template.Options.RawTemplate = data } return template, nil diff --git a/pkg/templates/compile_test.go b/pkg/templates/compile_test.go index 91a858bd7..34c22b0f2 100644 --- a/pkg/templates/compile_test.go +++ b/pkg/templates/compile_test.go @@ -31,25 +31,25 @@ import ( "github.com/stretchr/testify/require" ) -var executerOpts protocols.ExecutorOptions +var executerOpts *protocols.ExecutorOptions func setup() { options := testutils.DefaultOptions testutils.Init(options) progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0) - executerOpts = protocols.ExecutorOptions{ - Output: testutils.NewMockOutputWriter(options.OmitTemplate), - Options: options, - Progress: progressImpl, - ProjectFile: nil, - IssuesClient: nil, - Browser: nil, - Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory), - RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second), - Parser: templates.NewParser(), + executerOpts = &protocols.ExecutorOptions{ + Output: testutils.NewMockOutputWriter(options.OmitTemplate), + Options: options, + Progress: progressImpl, + ProjectFile: nil, + IssuesClient: nil, + Browser: nil, + Catalog: disk.NewCatalog(config.DefaultConfig.TemplatesDirectory), + RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second), + Parser: templates.NewParser(), } - workflowLoader, err := workflow.NewLoader(&executerOpts) + workflowLoader, err := workflow.NewLoader(executerOpts) if err != nil { log.Fatalf("Could not create workflow loader: %s\n", err) } diff --git a/pkg/templates/parser.go b/pkg/templates/parser.go index 7f481dc85..b99529916 100644 --- a/pkg/templates/parser.go +++ b/pkg/templates/parser.go @@ -3,6 +3,8 @@ package templates import ( "fmt" "io" + "strings" + "sync" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" @@ -11,6 +13,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/utils/stats" yamlutil "github.com/projectdiscovery/nuclei/v3/pkg/utils/yaml" fileutil "github.com/projectdiscovery/utils/file" + "gopkg.in/yaml.v2" ) @@ -22,6 +25,7 @@ type Parser struct { // this cache might potentially contain references to heap objects // it's recommended to always empty it at the end of execution compiledTemplatesCache *Cache + sync.Mutex } func NewParser() *Parser { @@ -45,6 +49,13 @@ func (p *Parser) Cache() *Cache { return p.parsedTemplatesCache } +func checkOpenFileError(err error) bool { + if err != nil && strings.Contains(err.Error(), "too many open files") { + panic(err) + } + return false +} + // LoadTemplate returns true if the template is valid and matches the filtering criteria. func (p *Parser) LoadTemplate(templatePath string, t any, extraTags []string, catalog catalog.Catalog) (bool, error) { tagFilter, ok := t.(*TagFilter) @@ -53,6 +64,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.Msgf(templatePath, templateParseError) } template, ok := t.(*Template) @@ -72,6 +84,7 @@ func (p *Parser) LoadTemplate(templatePath string, t any, extraTags []string, ca ret, err := isTemplateInfoMetadataMatch(tagFilter, template, extraTags) if err != nil { + checkOpenFileError(err) return ret, ErrCouldNotLoadTemplate.Msgf(templatePath, err) } // if template loaded then check the template for optional fields to add warnings @@ -79,6 +92,7 @@ func (p *Parser) LoadTemplate(templatePath string, t any, extraTags []string, ca validationWarning := validateTemplateOptionalFields(template) if validationWarning != nil { stats.Increment(SyntaxWarningStats) + checkOpenFileError(validationWarning) return ret, ErrCouldNotLoadTemplate.Msgf(templatePath, validationWarning) } } @@ -97,8 +111,8 @@ func (p *Parser) ParseTemplate(templatePath string, catalog catalog.Catalog) (an return nil, err } defer func() { - _ = reader.Close() - }() + _ = reader.Close() + }() data, err := io.ReadAll(reader) if err != nil { @@ -157,3 +171,84 @@ func (p *Parser) LoadWorkflow(templatePath string, catalog catalog.Catalog) (boo return false, nil } + +// CloneForExecutionId creates a clone with updated execution IDs +func (p *Parser) CloneForExecutionId(xid string) *Parser { + p.Lock() + defer p.Unlock() + + newParser := &Parser{ + ShouldValidate: p.ShouldValidate, + NoStrictSyntax: p.NoStrictSyntax, + parsedTemplatesCache: NewCache(), + compiledTemplatesCache: NewCache(), + } + + for k, tpl := range p.parsedTemplatesCache.items.Map { + newTemplate := templateUpdateExecutionId(tpl.template, xid) + newParser.parsedTemplatesCache.Store(k, newTemplate, []byte(tpl.raw), tpl.err) + } + + for k, tpl := range p.compiledTemplatesCache.items.Map { + newTemplate := templateUpdateExecutionId(tpl.template, xid) + newParser.compiledTemplatesCache.Store(k, newTemplate, []byte(tpl.raw), tpl.err) + } + + return newParser +} + +func templateUpdateExecutionId(tpl *Template, xid string) *Template { + // TODO: This is a no-op today since options are patched in elsewhere, but we're keeping this + // for future work where we may need additional tweaks per template instance. + return tpl + + /* + templateBase := *tpl + var newOpts *protocols.ExecutorOptions + // Swap out the types.Options execution ID attached to the template + if templateBase.Options != nil { + optionsBase := *templateBase.Options //nolint + templateBase.Options = &optionsBase + if templateBase.Options.Options != nil { + optionsOptionsBase := *templateBase.Options.Options //nolint + templateBase.Options.Options = &optionsOptionsBase + templateBase.Options.Options.ExecutionId = xid + newOpts = templateBase.Options + } + } + if newOpts == nil { + return &templateBase + } + for _, r := range templateBase.RequestsDNS { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsHTTP { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsCode { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsFile { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsHeadless { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsNetwork { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsJavascript { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsSSL { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsWHOIS { + r.UpdateOptions(newOpts) + } + for _, r := range templateBase.RequestsWebsocket { + r.UpdateOptions(newOpts) + } + return &templateBase + */ +} diff --git a/pkg/templates/template_sign.go b/pkg/templates/template_sign.go index 1eb09a447..d9a1417eb 100644 --- a/pkg/templates/template_sign.go +++ b/pkg/templates/template_sign.go @@ -89,7 +89,7 @@ func SignTemplate(templateSigner *signer.TemplateSigner, templatePath string) er func getTemplate(templatePath string) (*Template, []byte, error) { catalog := disk.NewCatalog(filepath.Dir(templatePath)) - executerOpts := protocols.ExecutorOptions{ + executerOpts := &protocols.ExecutorOptions{ Catalog: catalog, Options: defaultOpts, TemplatePath: templatePath, diff --git a/pkg/testutils/fuzzplayground/db.go b/pkg/testutils/fuzzplayground/db.go index 47b506adb..87c490a70 100644 --- a/pkg/testutils/fuzzplayground/db.go +++ b/pkg/testutils/fuzzplayground/db.go @@ -135,8 +135,8 @@ func getUnsanitizedPostsByLang(db *sql.DB, lang string) ([]Posts, error) { return nil, err } defer func() { - _ = rows.Close() - }() + _ = rows.Close() + }() for rows.Next() { var post Posts diff --git a/pkg/testutils/fuzzplayground/server.go b/pkg/testutils/fuzzplayground/server.go index 519a17d51..5278c1236 100644 --- a/pkg/testutils/fuzzplayground/server.go +++ b/pkg/testutils/fuzzplayground/server.go @@ -81,8 +81,8 @@ func requestHandler(ctx echo.Context) error { return ctx.HTML(500, err.Error()) } defer func() { - _ = data.Body.Close() - }() + _ = data.Body.Close() + }() body, _ := io.ReadAll(data.Body) return ctx.HTML(200, fmt.Sprintf(bodyTemplate, string(body))) @@ -175,8 +175,8 @@ func resetPasswordHandler(c echo.Context) error { return c.JSON(500, "Something went wrong") } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() return c.JSON(200, "Password reset successfully") } @@ -189,8 +189,8 @@ func hostHeaderLabHandler(c echo.Context) error { return c.JSON(500, "Something went wrong") } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() c.Response().Header().Set("Content-Type", resp.Header.Get("Content-Type")) c.Response().WriteHeader(resp.StatusCode) _, err = io.Copy(c.Response().Writer, resp.Body) diff --git a/pkg/testutils/integration.go b/pkg/testutils/integration.go index 3c5e33f6d..d93e87011 100644 --- a/pkg/testutils/integration.go +++ b/pkg/testutils/integration.go @@ -339,8 +339,8 @@ func NewWebsocketServer(path string, handler func(conn net.Conn), originValidate } go func() { defer func() { - _ = conn.Close() - }() + _ = conn.Close() + }() handler(conn) }() diff --git a/pkg/tmplexec/exec.go b/pkg/tmplexec/exec.go index c59b6c123..acf72a3c0 100644 --- a/pkg/tmplexec/exec.go +++ b/pkg/tmplexec/exec.go @@ -7,7 +7,7 @@ import ( "sync/atomic" "time" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/js/compiler" "github.com/projectdiscovery/nuclei/v3/pkg/operators" diff --git a/pkg/tmplexec/flow/builtin/dedupe.go b/pkg/tmplexec/flow/builtin/dedupe.go index 729a7adf2..369289db1 100644 --- a/pkg/tmplexec/flow/builtin/dedupe.go +++ b/pkg/tmplexec/flow/builtin/dedupe.go @@ -4,7 +4,7 @@ import ( "crypto/md5" "reflect" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/types" ) diff --git a/pkg/tmplexec/flow/flow_executor.go b/pkg/tmplexec/flow/flow_executor.go index 2334eecee..226a0c432 100644 --- a/pkg/tmplexec/flow/flow_executor.go +++ b/pkg/tmplexec/flow/flow_executor.go @@ -7,7 +7,7 @@ import ( "strings" "sync/atomic" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/js/compiler" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" @@ -208,7 +208,7 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error { for proto := range f.protoFunctions { _ = runtime.GlobalObject().Delete(proto) } - + runtime.RemoveContextValue("executionId") }() // TODO(dwisiswant0): remove this once we get the RCA. @@ -249,6 +249,8 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error { return err } + runtime.SetContextValue("executionId", f.options.Options.ExecutionId) + // pass flow and execute the js vm and handle errors _, err := runtime.RunProgram(f.program) f.reconcileProgress() @@ -295,8 +297,8 @@ func (f *FlowExecutor) ReadDataFromFile(payload string) ([]string, error) { return values, err } defer func() { - _ = reader.Close() - }() + _ = reader.Close() + }() bin, err := io.ReadAll(reader) if err != nil { return values, err diff --git a/pkg/tmplexec/flow/flow_executor_test.go b/pkg/tmplexec/flow/flow_executor_test.go index 217a253d3..21518194e 100644 --- a/pkg/tmplexec/flow/flow_executor_test.go +++ b/pkg/tmplexec/flow/flow_executor_test.go @@ -19,14 +19,14 @@ import ( "github.com/stretchr/testify/require" ) -var executerOpts protocols.ExecutorOptions +var executerOpts *protocols.ExecutorOptions func setup() { options := testutils.DefaultOptions testutils.Init(options) progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0) - executerOpts = protocols.ExecutorOptions{ + executerOpts = &protocols.ExecutorOptions{ Output: testutils.NewMockOutputWriter(options.OmitTemplate), Options: options, Progress: progressImpl, @@ -37,7 +37,7 @@ func setup() { RateLimiter: ratelimit.New(context.Background(), uint(options.RateLimit), time.Second), Parser: templates.NewParser(), } - workflowLoader, err := workflow.NewLoader(&executerOpts) + workflowLoader, err := workflow.NewLoader(executerOpts) if err != nil { log.Fatalf("Could not create workflow loader: %s\n", err) } diff --git a/pkg/tmplexec/flow/flow_internal.go b/pkg/tmplexec/flow/flow_internal.go index 927b2d6c9..9a8d807cc 100644 --- a/pkg/tmplexec/flow/flow_internal.go +++ b/pkg/tmplexec/flow/flow_internal.go @@ -4,7 +4,7 @@ import ( "fmt" "sync/atomic" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" mapsutil "github.com/projectdiscovery/utils/maps" @@ -20,7 +20,7 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma f.options.GetTemplateCtx(f.ctx.Input.MetaInput).Merge(variableMap) // merge all variables into template context // to avoid polling update template variables everytime we execute a protocol - var m = f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll() + m := f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll() _ = runtime.Set("template", m) }() matcherStatus := &atomic.Bool{} // due to interactsh matcher polling logic this needs to be atomic bool diff --git a/pkg/tmplexec/flow/vm.go b/pkg/tmplexec/flow/vm.go index 88033c250..81c9c4c07 100644 --- a/pkg/tmplexec/flow/vm.go +++ b/pkg/tmplexec/flow/vm.go @@ -5,7 +5,7 @@ import ( "reflect" "sync" - "github.com/dop251/goja" + "github.com/Mzack9999/goja" "github.com/logrusorgru/aurora" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/js/gojs" diff --git a/pkg/tmplexec/multiproto/multi_test.go b/pkg/tmplexec/multiproto/multi_test.go index 8a65f4fc9..6be10dc77 100644 --- a/pkg/tmplexec/multiproto/multi_test.go +++ b/pkg/tmplexec/multiproto/multi_test.go @@ -21,14 +21,14 @@ import ( "github.com/stretchr/testify/require" ) -var executerOpts protocols.ExecutorOptions +var executerOpts *protocols.ExecutorOptions func setup() { options := testutils.DefaultOptions testutils.Init(options) progressImpl, _ := progress.NewStatsTicker(0, false, false, false, 0) - executerOpts = protocols.ExecutorOptions{ + executerOpts = &protocols.ExecutorOptions{ Output: testutils.NewMockOutputWriter(options.OmitTemplate), Options: options, Progress: progressImpl, @@ -40,7 +40,7 @@ func setup() { Parser: templates.NewParser(), InputHelper: input.NewHelper(), } - workflowLoader, err := workflow.NewLoader(&executerOpts) + workflowLoader, err := workflow.NewLoader(executerOpts) if err != nil { log.Fatalf("Could not create workflow loader: %s\n", err) } diff --git a/pkg/types/types.go b/pkg/types/types.go index 41c95ef68..656ff8447 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -5,9 +5,11 @@ import ( "os" "path/filepath" "strings" + "sync" "time" "github.com/projectdiscovery/goflags" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" @@ -444,11 +446,236 @@ type Options struct { // LoadHelperFileFunction is a function that will be used to execute LoadHelperFile. // If none is provided, then the default implementation will be used. LoadHelperFileFunction LoadHelperFileFunction + // Logger is the gologger instance for this optionset + Logger *gologger.Logger + // NoCacheTemplates disables caching of templates + DoNotCacheTemplates bool + // Unique identifier of the execution session + ExecutionId string + // Parser is a cached parser for the template store + Parser any // timeouts contains various types of timeouts used in nuclei // these timeouts are derived from dial-timeout (-timeout) with known multipliers // This is internally managed and does not need to be set by user by explicitly setting // this overrides the default/derived one timeouts *Timeouts + // m is a mutex to protect timeouts from concurrent access + m sync.Mutex +} + +func (options *Options) Copy() *Options { + optCopy := &Options{ + Tags: options.Tags, + ExcludeTags: options.ExcludeTags, + Workflows: options.Workflows, + WorkflowURLs: options.WorkflowURLs, + Templates: options.Templates, + TemplateURLs: options.TemplateURLs, + AITemplatePrompt: options.AITemplatePrompt, + RemoteTemplateDomainList: options.RemoteTemplateDomainList, + ExcludedTemplates: options.ExcludedTemplates, + ExcludeMatchers: options.ExcludeMatchers, + CustomHeaders: options.CustomHeaders, + Vars: options.Vars, + Severities: options.Severities, + ExcludeSeverities: options.ExcludeSeverities, + Authors: options.Authors, + Protocols: options.Protocols, + ExcludeProtocols: options.ExcludeProtocols, + IncludeTags: options.IncludeTags, + IncludeTemplates: options.IncludeTemplates, + IncludeIds: options.IncludeIds, + ExcludeIds: options.ExcludeIds, + InternalResolversList: options.InternalResolversList, + ProjectPath: options.ProjectPath, + InteractshURL: options.InteractshURL, + InteractshToken: options.InteractshToken, + Targets: options.Targets, + ExcludeTargets: options.ExcludeTargets, + TargetsFilePath: options.TargetsFilePath, + Resume: options.Resume, + Output: options.Output, + ProxyInternal: options.ProxyInternal, + ListDslSignatures: options.ListDslSignatures, + Proxy: options.Proxy, + AliveHttpProxy: options.AliveHttpProxy, + AliveSocksProxy: options.AliveSocksProxy, + NewTemplatesDirectory: options.NewTemplatesDirectory, + TraceLogFile: options.TraceLogFile, + ErrorLogFile: options.ErrorLogFile, + ReportingDB: options.ReportingDB, + ReportingConfig: options.ReportingConfig, + MarkdownExportDirectory: options.MarkdownExportDirectory, + MarkdownExportSortMode: options.MarkdownExportSortMode, + SarifExport: options.SarifExport, + ResolversFile: options.ResolversFile, + StatsInterval: options.StatsInterval, + MetricsPort: options.MetricsPort, + MaxHostError: options.MaxHostError, + TrackError: options.TrackError, + NoHostErrors: options.NoHostErrors, + BulkSize: options.BulkSize, + TemplateThreads: options.TemplateThreads, + HeadlessBulkSize: options.HeadlessBulkSize, + HeadlessTemplateThreads: options.HeadlessTemplateThreads, + Timeout: options.Timeout, + Retries: options.Retries, + RateLimit: options.RateLimit, + RateLimitDuration: options.RateLimitDuration, + RateLimitMinute: options.RateLimitMinute, + PageTimeout: options.PageTimeout, + InteractionsCacheSize: options.InteractionsCacheSize, + InteractionsPollDuration: options.InteractionsPollDuration, + InteractionsEviction: options.InteractionsEviction, + InteractionsCoolDownPeriod: options.InteractionsCoolDownPeriod, + MaxRedirects: options.MaxRedirects, + FollowRedirects: options.FollowRedirects, + FollowHostRedirects: options.FollowHostRedirects, + OfflineHTTP: options.OfflineHTTP, + ForceAttemptHTTP2: options.ForceAttemptHTTP2, + StatsJSON: options.StatsJSON, + Headless: options.Headless, + ShowBrowser: options.ShowBrowser, + HeadlessOptionalArguments: options.HeadlessOptionalArguments, + DisableClustering: options.DisableClustering, + UseInstalledChrome: options.UseInstalledChrome, + SystemResolvers: options.SystemResolvers, + ShowActions: options.ShowActions, + Metrics: options.Metrics, + Debug: options.Debug, + DebugRequests: options.DebugRequests, + DebugResponse: options.DebugResponse, + DisableHTTPProbe: options.DisableHTTPProbe, + LeaveDefaultPorts: options.LeaveDefaultPorts, + AutomaticScan: options.AutomaticScan, + Silent: options.Silent, + Validate: options.Validate, + NoStrictSyntax: options.NoStrictSyntax, + Verbose: options.Verbose, + VerboseVerbose: options.VerboseVerbose, + ShowVarDump: options.ShowVarDump, + VarDumpLimit: options.VarDumpLimit, + NoColor: options.NoColor, + UpdateTemplates: options.UpdateTemplates, + JSONL: options.JSONL, + JSONRequests: options.JSONRequests, + OmitRawRequests: options.OmitRawRequests, + HTTPStats: options.HTTPStats, + OmitTemplate: options.OmitTemplate, + JSONExport: options.JSONExport, + JSONLExport: options.JSONLExport, + Redact: options.Redact, + EnableProgressBar: options.EnableProgressBar, + TemplateDisplay: options.TemplateDisplay, + TemplateList: options.TemplateList, + TagList: options.TagList, + HangMonitor: options.HangMonitor, + Stdin: options.Stdin, + StopAtFirstMatch: options.StopAtFirstMatch, + Stream: options.Stream, + NoMeta: options.NoMeta, + Timestamp: options.Timestamp, + Project: options.Project, + NewTemplates: options.NewTemplates, + NewTemplatesWithVersion: options.NewTemplatesWithVersion, + NoInteractsh: options.NoInteractsh, + EnvironmentVariables: options.EnvironmentVariables, + MatcherStatus: options.MatcherStatus, + ClientCertFile: options.ClientCertFile, + ClientKeyFile: options.ClientKeyFile, + ClientCAFile: options.ClientCAFile, + ZTLS: options.ZTLS, + AllowLocalFileAccess: options.AllowLocalFileAccess, + RestrictLocalNetworkAccess: options.RestrictLocalNetworkAccess, + ShowMatchLine: options.ShowMatchLine, + EnablePprof: options.EnablePprof, + StoreResponse: options.StoreResponse, + StoreResponseDir: options.StoreResponseDir, + DisableRedirects: options.DisableRedirects, + SNI: options.SNI, + InputFileMode: options.InputFileMode, + DialerKeepAlive: options.DialerKeepAlive, + Interface: options.Interface, + SourceIP: options.SourceIP, + AttackType: options.AttackType, + ResponseReadSize: options.ResponseReadSize, + ResponseSaveSize: options.ResponseSaveSize, + HealthCheck: options.HealthCheck, + InputReadTimeout: options.InputReadTimeout, + DisableStdin: options.DisableStdin, + IncludeConditions: options.IncludeConditions, + Uncover: options.Uncover, + UncoverQuery: options.UncoverQuery, + UncoverEngine: options.UncoverEngine, + UncoverField: options.UncoverField, + UncoverLimit: options.UncoverLimit, + UncoverRateLimit: options.UncoverRateLimit, + ScanAllIPs: options.ScanAllIPs, + IPVersion: options.IPVersion, + PublicTemplateDisableDownload: options.PublicTemplateDisableDownload, + GitHubToken: options.GitHubToken, + GitHubTemplateRepo: options.GitHubTemplateRepo, + GitHubTemplateDisableDownload: options.GitHubTemplateDisableDownload, + GitLabServerURL: options.GitLabServerURL, + GitLabToken: options.GitLabToken, + GitLabTemplateRepositoryIDs: options.GitLabTemplateRepositoryIDs, + GitLabTemplateDisableDownload: options.GitLabTemplateDisableDownload, + AwsProfile: options.AwsProfile, + AwsAccessKey: options.AwsAccessKey, + AwsSecretKey: options.AwsSecretKey, + AwsBucketName: options.AwsBucketName, + AwsRegion: options.AwsRegion, + AwsTemplateDisableDownload: options.AwsTemplateDisableDownload, + AzureContainerName: options.AzureContainerName, + AzureTenantID: options.AzureTenantID, + AzureClientID: options.AzureClientID, + AzureClientSecret: options.AzureClientSecret, + AzureServiceURL: options.AzureServiceURL, + AzureTemplateDisableDownload: options.AzureTemplateDisableDownload, + ScanStrategy: options.ScanStrategy, + FuzzingType: options.FuzzingType, + FuzzingMode: options.FuzzingMode, + TlsImpersonate: options.TlsImpersonate, + DisplayFuzzPoints: options.DisplayFuzzPoints, + FuzzAggressionLevel: options.FuzzAggressionLevel, + FuzzParamFrequency: options.FuzzParamFrequency, + CodeTemplateSignaturePublicKey: options.CodeTemplateSignaturePublicKey, + CodeTemplateSignatureAlgorithm: options.CodeTemplateSignatureAlgorithm, + SignTemplates: options.SignTemplates, + EnableCodeTemplates: options.EnableCodeTemplates, + DisableUnsignedTemplates: options.DisableUnsignedTemplates, + EnableSelfContainedTemplates: options.EnableSelfContainedTemplates, + EnableGlobalMatchersTemplates: options.EnableGlobalMatchersTemplates, + EnableFileTemplates: options.EnableFileTemplates, + EnableCloudUpload: options.EnableCloudUpload, + ScanID: options.ScanID, + ScanName: options.ScanName, + ScanUploadFile: options.ScanUploadFile, + TeamID: options.TeamID, + JsConcurrency: options.JsConcurrency, + SecretsFile: options.SecretsFile, + PreFetchSecrets: options.PreFetchSecrets, + FormatUseRequiredOnly: options.FormatUseRequiredOnly, + SkipFormatValidation: options.SkipFormatValidation, + PayloadConcurrency: options.PayloadConcurrency, + ProbeConcurrency: options.ProbeConcurrency, + DAST: options.DAST, + DASTServer: options.DASTServer, + DASTServerToken: options.DASTServerToken, + DASTServerAddress: options.DASTServerAddress, + DASTReport: options.DASTReport, + Scope: options.Scope, + OutOfScope: options.OutOfScope, + HttpApiEndpoint: options.HttpApiEndpoint, + ListTemplateProfiles: options.ListTemplateProfiles, + LoadHelperFileFunction: options.LoadHelperFileFunction, + Logger: options.Logger, + DoNotCacheTemplates: options.DoNotCacheTemplates, + ExecutionId: options.ExecutionId, + Parser: options.Parser, + } + optCopy.SetTimeouts(options.timeouts) + return optCopy } // SetTimeouts sets the timeout variants to use for the executor @@ -458,6 +685,8 @@ func (opts *Options) SetTimeouts(t *Timeouts) { // GetTimeouts returns the timeout variants to use for the executor func (eo *Options) GetTimeouts() *Timeouts { + eo.m.Lock() + defer eo.m.Unlock() if eo.timeouts != nil { // redundant but apply to avoid any potential issues eo.timeouts.ApplyDefaults() @@ -645,6 +874,20 @@ func (o *Options) GetValidAbsPath(helperFilePath, templatePath string) (string, return "", errorutil.New("access to helper file %v denied", helperFilePath) } +// SetExecutionID sets the execution ID for the options +func (options *Options) SetExecutionID(id string) { + options.m.Lock() + defer options.m.Unlock() + options.ExecutionId = id +} + +// GetExecutionID gets the execution ID for the options +func (options *Options) GetExecutionID() string { + options.m.Lock() + defer options.m.Unlock() + return options.ExecutionId +} + // isHomeDir checks if given is home directory func isHomeDir(path string) bool { homeDir := folderutil.HomeDirOrDefault("") From a13ea39461e039c1380967e08e3a1ec19ba3911d Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 12 Jul 2025 03:46:35 +0700 Subject: [PATCH 059/135] build(docker): bump builder image `golang:1.23-alpine` => `golang:1.24-alpine` (#6316) Signed-off-by: Dwi Siswanto --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1c44e7056..eebc24add 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build -FROM golang:1.23-alpine AS builder +FROM golang:1.24-alpine AS builder RUN apk add build-base WORKDIR /app From 1079498182b6b9ff464536201b18f6329d1a93a9 Mon Sep 17 00:00:00 2001 From: gopherorg Date: Sat, 12 Jul 2025 05:20:47 +0800 Subject: [PATCH 060/135] refactor: use maps.Copy for cleaner map handling (#6283) Signed-off-by: gopherorg --- pkg/input/formats/openapi/examples.go | 5 ++--- pkg/js/gojs/gojs.go | 5 ++--- pkg/operators/operators.go | 5 ++--- pkg/projectfile/httputil.go | 5 ++--- pkg/protocols/common/generators/generators.go | 5 ++--- pkg/protocols/common/generators/maps.go | 5 ++--- pkg/protocols/dns/request.go | 9 +++------ pkg/protocols/file/request.go | 9 +++------ pkg/protocols/http/operators.go | 5 ++--- pkg/protocols/http/request.go | 9 +++------ pkg/protocols/javascript/js.go | 9 +++------ pkg/protocols/network/request.go | 17 +++++------------ pkg/protocols/offlinehttp/operators.go | 5 ++--- pkg/protocols/ssl/ssl.go | 9 +++------ pkg/protocols/websocket/websocket.go | 13 ++++--------- 15 files changed, 40 insertions(+), 75 deletions(-) diff --git a/pkg/input/formats/openapi/examples.go b/pkg/input/formats/openapi/examples.go index 2c79d5c89..6fb294cbf 100644 --- a/pkg/input/formats/openapi/examples.go +++ b/pkg/input/formats/openapi/examples.go @@ -2,6 +2,7 @@ package openapi import ( "fmt" + "maps" "slices" "github.com/getkin/kin-openapi/openapi3" @@ -162,9 +163,7 @@ func openAPIExample(schema *openapi3.Schema, cache map[*openapi3.Schema]*cachedS return nil, ErrNoExample } - for k, v := range value { - example[k] = v - } + maps.Copy(example, value) } return example, nil } diff --git a/pkg/js/gojs/gojs.go b/pkg/js/gojs/gojs.go index 5d4af6e87..e82dcb6f3 100644 --- a/pkg/js/gojs/gojs.go +++ b/pkg/js/gojs/gojs.go @@ -2,6 +2,7 @@ package gojs import ( "context" + "maps" "reflect" "sync" @@ -103,9 +104,7 @@ func wrapModuleFunc(runtime *goja.Runtime, fn interface{}) interface{} { } func (p *GojaModule) Set(objects Objects) Module { - for k, v := range objects { - p.sets[k] = v - } + maps.Copy(p.sets, objects) return p } diff --git a/pkg/operators/operators.go b/pkg/operators/operators.go index 1fb1ab1c5..ed2f0c4d2 100644 --- a/pkg/operators/operators.go +++ b/pkg/operators/operators.go @@ -2,6 +2,7 @@ package operators import ( "fmt" + "maps" "strconv" "strings" @@ -218,9 +219,7 @@ func (r *Result) Merge(result *Result) { r.DynamicValues[k] = sliceutil.Dedupe(append(r.DynamicValues[k], v...)) } } - for k, v := range result.PayloadValues { - r.PayloadValues[k] = v - } + maps.Copy(r.PayloadValues, result.PayloadValues) } // MatchFunc performs matching operation for a matcher on model and returns true or false. diff --git a/pkg/projectfile/httputil.go b/pkg/projectfile/httputil.go index dafeff3fd..078bd6841 100644 --- a/pkg/projectfile/httputil.go +++ b/pkg/projectfile/httputil.go @@ -6,6 +6,7 @@ import ( "encoding/gob" "encoding/hex" "io" + "maps" "net/http" ) @@ -85,9 +86,7 @@ func toInternalResponse(resp *http.Response, body []byte) *InternalResponse { intResp.HTTPMinor = resp.ProtoMinor intResp.StatusCode = resp.StatusCode intResp.StatusReason = resp.Status - for k, v := range resp.Header { - intResp.Headers[k] = v - } + maps.Copy(intResp.Headers, resp.Header) intResp.Body = body return intResp } diff --git a/pkg/protocols/common/generators/generators.go b/pkg/protocols/common/generators/generators.go index 5711b445f..fbb7f1554 100644 --- a/pkg/protocols/common/generators/generators.go +++ b/pkg/protocols/common/generators/generators.go @@ -4,6 +4,7 @@ package generators import ( "github.com/pkg/errors" + "maps" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" "github.com/projectdiscovery/nuclei/v3/pkg/types" @@ -32,9 +33,7 @@ func New(payloads map[string]interface{}, attackType AttackType, templatePath st if err != nil { return nil, errors.Wrap(err, "could not parse payloads with aggression") } - for k, v := range values { - payloadsFinal[k] = v - } + maps.Copy(payloadsFinal, values) default: payloadsFinal[payloadName] = v } diff --git a/pkg/protocols/common/generators/maps.go b/pkg/protocols/common/generators/maps.go index 72bf705d8..ed2fc3a64 100644 --- a/pkg/protocols/common/generators/maps.go +++ b/pkg/protocols/common/generators/maps.go @@ -1,6 +1,7 @@ package generators import ( + maps0 "maps" "reflect" ) @@ -47,9 +48,7 @@ func MergeMapsMany(maps ...interface{}) map[string][]string { func MergeMaps(maps ...map[string]interface{}) map[string]interface{} { merged := make(map[string]interface{}) for _, m := range maps { - for k, v := range m { - merged[k] = v - } + maps0.Copy(merged, m) } return merged } diff --git a/pkg/protocols/dns/request.go b/pkg/protocols/dns/request.go index 6e82c047b..3cc0cd715 100644 --- a/pkg/protocols/dns/request.go +++ b/pkg/protocols/dns/request.go @@ -3,6 +3,7 @@ package dns import ( "encoding/hex" "fmt" + maps0 "maps" "strings" "sync" @@ -181,12 +182,8 @@ func (request *Request) execute(input *contextargs.Context, domain string, metad // expose response variables in proto_var format // this is no-op if the template is not a multi protocol template request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, outputEvent) - for k, v := range previous { - outputEvent[k] = v - } - for k, v := range vars { - outputEvent[k] = v - } + maps0.Copy(outputEvent, previous) + maps0.Copy(outputEvent, vars) // add variables from template context before matching/extraction if request.options.HasTemplateCtx(input.MetaInput) { outputEvent = generators.MergeMaps(outputEvent, request.options.GetTemplateCtx(input.MetaInput).GetAll()) diff --git a/pkg/protocols/file/request.go b/pkg/protocols/file/request.go index 8296dee17..853cbb602 100644 --- a/pkg/protocols/file/request.go +++ b/pkg/protocols/file/request.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "fmt" "io" + "maps" "os" "path/filepath" "strings" @@ -276,9 +277,7 @@ func (request *Request) findMatchesWithReader(reader io.Reader, input *contextar gologger.Verbose().Msgf("[%s] Processing file %s chunk %s/%s", request.options.TemplateID, filePath, processedBytes, totalBytesString) dslMap := request.responseToDSLMap(lineContent, input.MetaInput.Input, filePath) - for k, v := range previous { - dslMap[k] = v - } + maps.Copy(dslMap, previous) // add vars to template context request.options.AddTemplateVars(input.MetaInput, request.Type(), request.ID, dslMap) // add template context variables to DSL map @@ -347,9 +346,7 @@ func (request *Request) buildEvent(input, filePath string, fileMatches []FileMat exprLines := make(map[string][]int) exprBytes := make(map[string][]int) internalEvent := request.responseToDSLMap("", input, filePath) - for k, v := range previous { - internalEvent[k] = v - } + maps.Copy(internalEvent, previous) for _, fileMatch := range fileMatches { exprLines[fileMatch.Expr] = append(exprLines[fileMatch.Expr], fileMatch.Line) exprBytes[fileMatch.Expr] = append(exprBytes[fileMatch.Expr], fileMatch.ByteIndex) diff --git a/pkg/protocols/http/operators.go b/pkg/protocols/http/operators.go index f9da8043b..298da25e1 100644 --- a/pkg/protocols/http/operators.go +++ b/pkg/protocols/http/operators.go @@ -1,6 +1,7 @@ package http import ( + "maps" "net/http" "strings" "time" @@ -108,9 +109,7 @@ func (request *Request) getMatchPart(part string, data output.InternalEvent) (st // responseToDSLMap converts an HTTP response to a map for use in DSL matching func (request *Request) responseToDSLMap(resp *http.Response, host, matched, rawReq, rawResp, body, headers string, duration time.Duration, extra map[string]interface{}) output.InternalEvent { data := make(output.InternalEvent, 12+len(extra)+len(resp.Header)+len(resp.Cookies())) - for k, v := range extra { - data[k] = v - } + maps.Copy(data, extra) for _, cookie := range resp.Cookies() { request.setHashOrDefault(data, strings.ToLower(cookie.Name), cookie.Value) } diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index fc181d1c5..d9b30ab72 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "fmt" "io" + "maps" "net/http" "strconv" "strings" @@ -974,12 +975,8 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ if request.options.Interactsh != nil { request.options.Interactsh.MakePlaceholders(generatedRequest.interactshURLs, outputEvent) } - for k, v := range previousEvent { - finalEvent[k] = v - } - for k, v := range outputEvent { - finalEvent[k] = v - } + maps.Copy(finalEvent, previousEvent) + maps.Copy(finalEvent, outputEvent) // Add to history the current request number metadata if asked by the user. if request.NeedsRequestCondition() { diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index 0d4a41e03..fc5b30b98 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "maps" "net" "strings" "sync/atomic" @@ -304,9 +305,7 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV templateCtx := request.options.GetTemplateCtx(input.MetaInput) payloadValues := generators.BuildPayloadFromOptions(request.options.Options) - for k, v := range dynamicValues { - payloadValues[k] = v - } + maps.Copy(payloadValues, dynamicValues) payloadValues["Hostname"] = hostPort payloadValues["Host"] = hostname @@ -620,9 +619,7 @@ func (request *Request) generateEventData(input *contextargs.Context, values map } data := make(map[string]interface{}) - for k, v := range values { - data[k] = v - } + maps.Copy(data, values) data["type"] = request.Type().String() data["request-pre-condition"] = beautifyJavascript(request.PreCondition) data["request"] = beautifyJavascript(request.Code) diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index 189724033..24071763e 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -3,6 +3,7 @@ package network import ( "encoding/hex" "fmt" + maps0 "maps" "net" "net/url" "os" @@ -375,9 +376,7 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac // Run any internal extractors for the request here and add found values to map. if request.CompiledOperators != nil { values := request.CompiledOperators.ExecuteInternalExtractors(map[string]interface{}{input.Name: bufferStr}, request.Extract) - for k, v := range values { - payloads[k] = v - } + maps0.Copy(payloads, values) } } } @@ -427,15 +426,9 @@ func (request *Request) executeRequestWithPayloads(variables map[string]interfac if request.options.StopAtFirstMatch { outputEvent["stop-at-first-match"] = true } - for k, v := range previous { - outputEvent[k] = v - } - for k, v := range interimValues { - outputEvent[k] = v - } - for k, v := range inputEvents { - outputEvent[k] = v - } + maps0.Copy(outputEvent, previous) + maps0.Copy(outputEvent, interimValues) + maps0.Copy(outputEvent, inputEvents) if request.options.Interactsh != nil { request.options.Interactsh.MakePlaceholders(interactshURLs, outputEvent) } diff --git a/pkg/protocols/offlinehttp/operators.go b/pkg/protocols/offlinehttp/operators.go index be1a8b860..cbce83cb6 100644 --- a/pkg/protocols/offlinehttp/operators.go +++ b/pkg/protocols/offlinehttp/operators.go @@ -1,6 +1,7 @@ package offlinehttp import ( + "maps" "net/http" "strings" "time" @@ -103,9 +104,7 @@ func getMatchPart(part string, data output.InternalEvent) (string, bool) { // responseToDSLMap converts an HTTP response to a map for use in DSL matching func (request *Request) responseToDSLMap(resp *http.Response, host, matched, rawReq, rawResp, body, headers string, duration time.Duration, extra map[string]interface{}) output.InternalEvent { data := make(output.InternalEvent, 12+len(extra)+len(resp.Header)+len(resp.Cookies())) - for k, v := range extra { - data[k] = v - } + maps.Copy(data, extra) for _, cookie := range resp.Cookies() { data[strings.ToLower(cookie.Name)] = cookie.Value } diff --git a/pkg/protocols/ssl/ssl.go b/pkg/protocols/ssl/ssl.go index 8764d6f5f..72d666422 100644 --- a/pkg/protocols/ssl/ssl.go +++ b/pkg/protocols/ssl/ssl.go @@ -2,6 +2,7 @@ package ssl import ( "fmt" + "maps" "net" "strings" "time" @@ -206,9 +207,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa requestOptions := request.options payloadValues := generators.BuildPayloadFromOptions(request.options.Options) - for k, v := range dynamicValues { - payloadValues[k] = v - } + maps.Copy(payloadValues, dynamicValues) payloadValues["Hostname"] = hostPort payloadValues["Host"] = hostname @@ -271,9 +270,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa jsonDataString := string(jsonData) data := make(map[string]interface{}) - for k, v := range payloadValues { - data[k] = v - } + maps.Copy(data, payloadValues) data["type"] = request.Type().String() data["response"] = jsonDataString data["host"] = input.MetaInput.Input diff --git a/pkg/protocols/websocket/websocket.go b/pkg/protocols/websocket/websocket.go index 175002e53..84062373d 100644 --- a/pkg/protocols/websocket/websocket.go +++ b/pkg/protocols/websocket/websocket.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "fmt" "io" + "maps" "net" "net/http" "net/url" @@ -274,12 +275,8 @@ func (request *Request) executeRequestWithPayloads(target *contextargs.Context, request.options.AddTemplateVars(target.MetaInput, request.Type(), request.ID, data) data = generators.MergeMaps(data, request.options.GetTemplateCtx(target.MetaInput).GetAll()) - for k, v := range previous { - data[k] = v - } - for k, v := range events { - data[k] = v - } + maps.Copy(data, previous) + maps.Copy(data, events) event := eventcreator.CreateEventWithAdditionalOptions(request, data, requestOptions.Options.Debug || requestOptions.Options.DebugResponse, func(internalWrappedEvent *output.InternalWrappedEvent) { internalWrappedEvent.OperatorsResult.PayloadValues = payloadValues @@ -337,9 +334,7 @@ func (request *Request) readWriteInputWebsocket(conn net.Conn, payloadValues map // Run any internal extractors for the request here and add found values to map. if request.CompiledOperators != nil { values := request.CompiledOperators.ExecuteInternalExtractors(map[string]interface{}{req.Name: bufferStr}, protocols.MakeDefaultExtractFunc) - for k, v := range values { - inputEvents[k] = v - } + maps.Copy(inputEvents, values) } } } From 6bf3f147985c499113c74ab64e66d2fa6e351741 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 15 Jul 2025 02:34:29 -0500 Subject: [PATCH 061/135] avoid data races by using request clones --- pkg/protocols/http/request.go | 6 ++++-- pkg/protocols/http/utils.go | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index d9b30ab72..381f4d385 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -864,8 +864,10 @@ func (request *Request) executeRequest(input *contextargs.Context, generatedRequ var curlCommand string if !request.Unsafe && resp != nil && generatedRequest.request != nil && resp.Request != nil && !request.Race { bodyBytes, _ := generatedRequest.request.BodyBytes() - resp.Request.Body = io.NopCloser(bytes.NewReader(bodyBytes)) - command, err := http2curl.GetCurlCommand(generatedRequest.request.Request) + // Use a clone to avoid a race condition with the http transport + req := resp.Request.Clone(resp.Request.Context()) + req.Body = io.NopCloser(bytes.NewReader(bodyBytes)) + command, err := http2curl.GetCurlCommand(req) if err == nil && command != nil { curlCommand = command.String() } diff --git a/pkg/protocols/http/utils.go b/pkg/protocols/http/utils.go index 92aa870dc..90b2e8446 100644 --- a/pkg/protocols/http/utils.go +++ b/pkg/protocols/http/utils.go @@ -12,7 +12,8 @@ import ( // dump creates a dump of the http request in form of a byte slice func dump(req *generatedRequest, reqURL string) ([]byte, error) { if req.request != nil { - bin, err := req.request.Dump() + // 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, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", req.request.String()) } From 875941ce8d227ba6fed61dd053e7cc468b53d278 Mon Sep 17 00:00:00 2001 From: HD Moore Date: Tue, 15 Jul 2025 02:34:47 -0500 Subject: [PATCH 062/135] avoid data races using mutex for memguardian --- pkg/protocols/common/protocolstate/memguardian.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/protocols/common/protocolstate/memguardian.go b/pkg/protocols/common/protocolstate/memguardian.go index dac57cb7e..8a0d9699a 100644 --- a/pkg/protocols/common/protocolstate/memguardian.go +++ b/pkg/protocols/common/protocolstate/memguardian.go @@ -16,9 +16,12 @@ var ( MaxBytesBufferAllocOnLowMemory = env.GetEnvOrDefault("MEMGUARDIAN_ALLOC", 0) memTimer *time.Ticker cancelFunc context.CancelFunc + muGlobalChange sync.Mutex ) func StartActiveMemGuardian(ctx context.Context) { + muGlobalChange.Lock() + defer muGlobalChange.Unlock() if memguardian.DefaultMemGuardian == nil || memTimer != nil { return } @@ -42,6 +45,9 @@ func StartActiveMemGuardian(ctx context.Context) { } func StopActiveMemGuardian() { + muGlobalChange.Lock() + defer muGlobalChange.Unlock() + if memguardian.DefaultMemGuardian == nil { return } @@ -73,8 +79,6 @@ func GuardThreadsOrDefault(current int) int { return 1 } -var muGlobalChange sync.Mutex - // Global setting func GlobalGuardBytesBufferAlloc() error { if !muGlobalChange.TryLock() { From 5b89811b906f086e47fdf5357a5ee367f8f1daef Mon Sep 17 00:00:00 2001 From: HD Moore Date: Fri, 18 Jul 2025 13:40:58 -0500 Subject: [PATCH 063/135] 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 --- lib/config.go | 2 +- lib/sdk_private.go | 19 ++++ pkg/external/customtemplates/github_test.go | 21 ++-- pkg/installer/template.go | 2 +- pkg/js/libs/fs/fs.go | 21 ++-- pkg/protocols/common/protocolstate/file.go | 51 ++++++++- .../common/protocolstate/headless.go | 12 --- pkg/protocols/common/protocolstate/state.go | 4 +- pkg/protocols/dns/dnsclientpool/clientpool.go | 29 ++--- .../http/httpclientpool/clientpool.go | 12 +-- pkg/protocols/protocols.go | 61 ++++++++--- .../whois/rdapclientpool/clientpool.go | 10 +- pkg/templates/compile.go | 101 ++++++++++++------ pkg/templates/parser.go | 98 +++-------------- pkg/utils/capture_writer.go | 16 +++ 15 files changed, 279 insertions(+), 180 deletions(-) create mode 100644 pkg/utils/capture_writer.go diff --git a/lib/config.go b/lib/config.go index 5e96352b5..125442898 100644 --- a/lib/config.go +++ b/lib/config.go @@ -537,7 +537,7 @@ func WithResumeFile(file string) NucleiSDKOptions { } } -// WithLogger allows setting gologger instance +// WithLogger allows setting a shared gologger instance func WithLogger(logger *gologger.Logger) NucleiSDKOptions { return func(e *NucleiEngine) error { e.Logger = logger diff --git a/lib/sdk_private.go b/lib/sdk_private.go index 659187b20..d80a0fd06 100644 --- a/lib/sdk_private.go +++ b/lib/sdk_private.go @@ -231,6 +231,25 @@ func (e *NucleiEngine) init(ctx context.Context) error { } } + // Handle the case where the user passed an existing parser that we can use as a cache + if e.opts.Parser != nil { + if cachedParser, ok := e.opts.Parser.(*templates.Parser); ok { + e.parser = cachedParser + e.opts.Parser = cachedParser + e.executerOpts.Parser = cachedParser + e.executerOpts.Options.Parser = cachedParser + } + } + + // Create a new parser if necessary + if e.parser == nil { + op := templates.NewParser() + e.parser = op + e.opts.Parser = op + e.executerOpts.Parser = op + e.executerOpts.Options.Parser = op + } + e.engine = core.New(e.opts) e.engine.SetExecuterOptions(e.executerOpts) diff --git a/pkg/external/customtemplates/github_test.go b/pkg/external/customtemplates/github_test.go index 972706af1..4e429c020 100644 --- a/pkg/external/customtemplates/github_test.go +++ b/pkg/external/customtemplates/github_test.go @@ -1,23 +1,25 @@ package customtemplates import ( + "bytes" "context" "path/filepath" + "strings" "testing" "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/gologger/levels" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/testutils" - osutils "github.com/projectdiscovery/utils/os" + "github.com/projectdiscovery/nuclei/v3/pkg/utils" "github.com/stretchr/testify/require" ) func TestDownloadCustomTemplatesFromGitHub(t *testing.T) { - if osutils.IsOSX() { - t.Skip("skipping on macos due to unknown failure (works locally)") - } - - gologger.DefaultLogger.SetWriter(&testutils.NoopWriter{}) + // Capture output to check for rate limit errors + outputBuffer := &bytes.Buffer{} + gologger.DefaultLogger.SetWriter(&utils.CaptureWriter{Buffer: outputBuffer}) + gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug) templatesDirectory := t.TempDir() config.DefaultConfig.SetTemplatesDir(templatesDirectory) @@ -29,5 +31,12 @@ func TestDownloadCustomTemplatesFromGitHub(t *testing.T) { require.Nil(t, err, "could not create custom templates manager") ctm.Download(context.Background()) + + // Check if output contains rate limit error and skip test if so + output := outputBuffer.String() + if strings.Contains(output, "API rate limit exceeded") { + t.Skip("GitHub API rate limit exceeded, skipping test") + } + require.DirExists(t, filepath.Join(templatesDirectory, "github", "projectdiscovery", "nuclei-templates-test"), "cloned directory does not exists") } diff --git a/pkg/installer/template.go b/pkg/installer/template.go index 4ee784477..9e56f12a1 100644 --- a/pkg/installer/template.go +++ b/pkg/installer/template.go @@ -53,7 +53,7 @@ func (t *templateUpdateResults) String() string { }, } table := tablewriter.NewWriter(&buff) - table.Header("Total", "Added", "Modified", "Removed") + table.Header([]string{"Total", "Added", "Modified", "Removed"}) for _, v := range data { _ = table.Append(v) } diff --git a/pkg/js/libs/fs/fs.go b/pkg/js/libs/fs/fs.go index e3a3fd7bd..a5f77e875 100644 --- a/pkg/js/libs/fs/fs.go +++ b/pkg/js/libs/fs/fs.go @@ -1,6 +1,7 @@ package fs import ( + "context" "os" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" @@ -27,8 +28,9 @@ import ( // // when no itemType is provided, it will return both files and directories // const items = fs.ListDir('/tmp'); // ``` -func ListDir(path string, itemType string) ([]string, error) { - finalPath, err := protocolstate.NormalizePath(path) +func ListDir(ctx context.Context, path string, itemType string) ([]string, error) { + executionId := ctx.Value("executionId").(string) + finalPath, err := protocolstate.NormalizePathWithExecutionId(executionId, path) if err != nil { return nil, err } @@ -57,8 +59,9 @@ func ListDir(path string, itemType string) ([]string, error) { // // here permitted directories are $HOME/nuclei-templates/* // const content = fs.ReadFile('helpers/usernames.txt'); // ``` -func ReadFile(path string) ([]byte, error) { - finalPath, err := protocolstate.NormalizePath(path) +func ReadFile(ctx context.Context, path string) ([]byte, error) { + executionId := ctx.Value("executionId").(string) + finalPath, err := protocolstate.NormalizePathWithExecutionId(executionId, path) if err != nil { return nil, err } @@ -74,8 +77,8 @@ func ReadFile(path string) ([]byte, error) { // // here permitted directories are $HOME/nuclei-templates/* // const content = fs.ReadFileAsString('helpers/usernames.txt'); // ``` -func ReadFileAsString(path string) (string, error) { - bin, err := ReadFile(path) +func ReadFileAsString(ctx context.Context, path string) (string, error) { + bin, err := ReadFile(ctx, path) if err != nil { return "", err } @@ -91,14 +94,14 @@ func ReadFileAsString(path string) (string, error) { // const contents = fs.ReadFilesFromDir('helpers/ssh-keys'); // log(contents); // ``` -func ReadFilesFromDir(dir string) ([]string, error) { - files, err := ListDir(dir, "file") +func ReadFilesFromDir(ctx context.Context, dir string) ([]string, error) { + files, err := ListDir(ctx, dir, "file") if err != nil { return nil, err } var results []string for _, file := range files { - content, err := ReadFileAsString(dir + "/" + file) + content, err := ReadFileAsString(ctx, dir+"/"+file) if err != nil { return nil, err } diff --git a/pkg/protocols/common/protocolstate/file.go b/pkg/protocols/common/protocolstate/file.go index 9475aac0f..180d5a0b5 100644 --- a/pkg/protocols/common/protocolstate/file.go +++ b/pkg/protocols/common/protocolstate/file.go @@ -4,22 +4,65 @@ import ( "strings" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" + "github.com/projectdiscovery/nuclei/v3/pkg/types" errorutil "github.com/projectdiscovery/utils/errors" fileutil "github.com/projectdiscovery/utils/file" + mapsutil "github.com/projectdiscovery/utils/maps" ) var ( // LfaAllowed means local file access is allowed - LfaAllowed bool + LfaAllowed *mapsutil.SyncLockMap[string, bool] ) +func init() { + LfaAllowed = mapsutil.NewSyncLockMap[string, bool]() +} + +// IsLfaAllowed returns whether local file access is allowed +func IsLfaAllowed(options *types.Options) bool { + if GetLfaAllowed(options) { + return true + } + + // Otherwise look into dialers + dialers, ok := dialers.Get(options.ExecutionId) + if ok && dialers != nil { + dialers.Lock() + defer dialers.Unlock() + + return dialers.LocalFileAccessAllowed + } + + // otherwise just return option value + return options.AllowLocalFileAccess +} + +func SetLfaAllowed(options *types.Options) { + _ = LfaAllowed.Set(options.ExecutionId, options.AllowLocalFileAccess) +} + +func GetLfaAllowed(options *types.Options) bool { + allowed, ok := LfaAllowed.Get(options.ExecutionId) + + return ok && allowed +} + +func NormalizePathWithExecutionId(executionId string, filePath string) (string, error) { + options := &types.Options{ + ExecutionId: executionId, + } + return NormalizePath(options, filePath) +} + // Normalizepath normalizes path and returns absolute path // it returns error if path is not allowed // this respects the sandbox rules and only loads files from // allowed directories -func NormalizePath(filePath string) (string, error) { - // TODO: this should be tied to executionID - if LfaAllowed { +func NormalizePath(options *types.Options, filePath string) (string, error) { + // TODO: this should be tied to executionID using *types.Options + if IsLfaAllowed(options) { + // if local file access is allowed, we can return the absolute path return filePath, nil } cleaned, err := fileutil.ResolveNClean(filePath, config.DefaultConfig.GetTemplateDir()) diff --git a/pkg/protocols/common/protocolstate/headless.go b/pkg/protocols/common/protocolstate/headless.go index 4012e2da6..1d9970119 100644 --- a/pkg/protocols/common/protocolstate/headless.go +++ b/pkg/protocols/common/protocolstate/headless.go @@ -74,18 +74,6 @@ func InitHeadless(options *types.Options) { } } -// AllowLocalFileAccess returns whether local file access is allowed -func IsLfaAllowed(options *types.Options) bool { - dialers, ok := dialers.Get(options.ExecutionId) - if ok && dialers != nil { - dialers.Lock() - defer dialers.Unlock() - - return dialers.LocalFileAccessAllowed - } - return false -} - func IsRestrictLocalNetworkAccess(options *types.Options) bool { dialers, ok := dialers.Get(options.ExecutionId) if ok && dialers != nil { diff --git a/pkg/protocols/common/protocolstate/state.go b/pkg/protocols/common/protocolstate/state.go index 9f9a96a06..f72122c19 100644 --- a/pkg/protocols/common/protocolstate/state.go +++ b/pkg/protocols/common/protocolstate/state.go @@ -200,9 +200,7 @@ func initDialers(options *types.Options) error { StartActiveMemGuardian(context.Background()) - // TODO: this should be tied to executionID - // overidde global settings with latest options - LfaAllowed = options.AllowLocalFileAccess + SetLfaAllowed(options) return nil } diff --git a/pkg/protocols/dns/dnsclientpool/clientpool.go b/pkg/protocols/dns/dnsclientpool/clientpool.go index c1805be1c..ccbc1bc5d 100644 --- a/pkg/protocols/dns/dnsclientpool/clientpool.go +++ b/pkg/protocols/dns/dnsclientpool/clientpool.go @@ -8,12 +8,14 @@ import ( "github.com/pkg/errors" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/retryabledns" + mapsutil "github.com/projectdiscovery/utils/maps" ) var ( - poolMutex *sync.RWMutex + clientPool *mapsutil.SyncLockMap[string, *retryabledns.Client] + normalClient *retryabledns.Client - clientPool map[string]*retryabledns.Client + m sync.Mutex ) // defaultResolvers contains the list of resolvers known to be trusted. @@ -26,12 +28,14 @@ var defaultResolvers = []string{ // Init initializes the client pool implementation func Init(options *types.Options) error { + m.Lock() + defer m.Unlock() + // Don't create clients if already created in the past. if normalClient != nil { return nil } - poolMutex = &sync.RWMutex{} - clientPool = make(map[string]*retryabledns.Client) + clientPool = mapsutil.NewSyncLockMap[string, *retryabledns.Client]() resolvers := defaultResolvers if len(options.InternalResolversList) > 0 { @@ -45,6 +49,12 @@ func Init(options *types.Options) error { return nil } +func getNormalClient() *retryabledns.Client { + m.Lock() + defer m.Unlock() + return normalClient +} + // Configuration contains the custom configuration options for a client type Configuration struct { // Retries contains the retries for the dns client @@ -71,15 +81,12 @@ func (c *Configuration) Hash() string { // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration) (*retryabledns.Client, error) { if (configuration.Retries <= 1) && len(configuration.Resolvers) == 0 { - return normalClient, nil + return getNormalClient(), nil } hash := configuration.Hash() - poolMutex.RLock() - if client, ok := clientPool[hash]; ok { - poolMutex.RUnlock() + if client, ok := clientPool.Get(hash); ok { return client, nil } - poolMutex.RUnlock() resolvers := defaultResolvers if len(options.InternalResolversList) > 0 { @@ -95,9 +102,7 @@ func Get(options *types.Options, configuration *Configuration) (*retryabledns.Cl if err != nil { return nil, errors.Wrap(err, "could not create dns client") } + _ = clientPool.Set(hash, client) - poolMutex.Lock() - clientPool[hash] = client - poolMutex.Unlock() return client, nil } diff --git a/pkg/protocols/http/httpclientpool/clientpool.go b/pkg/protocols/http/httpclientpool/clientpool.go index 940ac3886..4fa0790a5 100644 --- a/pkg/protocols/http/httpclientpool/clientpool.go +++ b/pkg/protocols/http/httpclientpool/clientpool.go @@ -154,16 +154,16 @@ func GetRawHTTP(options *protocols.ExecutorOptions) *rawhttp.Client { return dialers.RawHTTPClient } - rawHttpOptions := rawhttp.DefaultOptions + rawHttpOptionsCopy := *rawhttp.DefaultOptions if options.Options.AliveHttpProxy != "" { - rawHttpOptions.Proxy = options.Options.AliveHttpProxy + rawHttpOptionsCopy.Proxy = options.Options.AliveHttpProxy } else if options.Options.AliveSocksProxy != "" { - rawHttpOptions.Proxy = options.Options.AliveSocksProxy + rawHttpOptionsCopy.Proxy = options.Options.AliveSocksProxy } else if dialers.Fastdialer != nil { - rawHttpOptions.FastDialer = dialers.Fastdialer + rawHttpOptionsCopy.FastDialer = dialers.Fastdialer } - rawHttpOptions.Timeout = options.Options.GetTimeouts().HttpTimeout - dialers.RawHTTPClient = rawhttp.NewClient(rawHttpOptions) + rawHttpOptionsCopy.Timeout = options.Options.GetTimeouts().HttpTimeout + dialers.RawHTTPClient = rawhttp.NewClient(&rawHttpOptionsCopy) return dialers.RawHTTPClient } diff --git a/pkg/protocols/protocols.go b/pkg/protocols/protocols.go index 30443eee6..197d79e0a 100644 --- a/pkg/protocols/protocols.go +++ b/pkg/protocols/protocols.go @@ -3,7 +3,6 @@ package protocols import ( "context" "encoding/base64" - "sync" "sync/atomic" "github.com/projectdiscovery/fastdialer/fastdialer" @@ -139,8 +138,6 @@ type ExecutorOptions struct { Logger *gologger.Logger // CustomFastdialer is a fastdialer dialer instance CustomFastdialer *fastdialer.Dialer - - m sync.Mutex } // todo: centralizing components is not feasible with current clogged architecture @@ -198,6 +195,11 @@ func (e *ExecutorOptions) HasTemplateCtx(input *contextargs.MetaInput) bool { // GetTemplateCtx returns template context for given input func (e *ExecutorOptions) GetTemplateCtx(input *contextargs.MetaInput) *contextargs.Context { scanId := input.GetScanHash(e.TemplateID) + if e.templateCtxStore == nil { + // if template context store is not initialized create it + e.CreateTemplateCtxStore() + } + // get template context from store templateCtx, ok := e.templateCtxStore.Get(scanId) if !ok { // if template context does not exist create new and add it to store and return it @@ -444,14 +446,49 @@ func (e *ExecutorOptions) ApplyNewEngineOptions(n *ExecutorOptions) { if e == nil || n == nil || n.Options == nil { return } - execID := n.Options.GetExecutionID() - e.SetExecutionID(execID) -} -// ApplyNewEngineOptions updates an existing ExecutorOptions with options from a new engine. This -// handles things like the ExecutionID that need to be updated. -func (e *ExecutorOptions) SetExecutionID(executorId string) { - e.m.Lock() - defer e.m.Unlock() - e.Options.SetExecutionID(executorId) + // The types.Options include the ExecutionID among other things + e.Options = n.Options.Copy() + + // Keep the template-specific fields, but replace the rest + /* + e.TemplateID = n.TemplateID + e.TemplatePath = n.TemplatePath + e.TemplateInfo = n.TemplateInfo + e.TemplateVerifier = n.TemplateVerifier + e.RawTemplate = n.RawTemplate + e.Variables = n.Variables + e.Constants = n.Constants + */ + e.Output = n.Output + e.Options = n.Options + e.IssuesClient = n.IssuesClient + e.Progress = n.Progress + e.RateLimiter = n.RateLimiter + e.Catalog = n.Catalog + e.ProjectFile = n.ProjectFile + e.Browser = n.Browser + e.Interactsh = n.Interactsh + e.HostErrorsCache = n.HostErrorsCache + e.StopAtFirstMatch = n.StopAtFirstMatch + e.ExcludeMatchers = n.ExcludeMatchers + e.InputHelper = n.InputHelper + e.FuzzParamsFrequency = n.FuzzParamsFrequency + e.FuzzStatsDB = n.FuzzStatsDB + e.DoNotCache = n.DoNotCache + e.Colorizer = n.Colorizer + e.WorkflowLoader = n.WorkflowLoader + e.ResumeCfg = n.ResumeCfg + e.ProtocolType = n.ProtocolType + e.Flow = n.Flow + e.IsMultiProtocol = n.IsMultiProtocol + e.templateCtxStore = n.templateCtxStore + e.JsCompiler = n.JsCompiler + e.AuthProvider = n.AuthProvider + e.TemporaryDirectory = n.TemporaryDirectory + e.Parser = n.Parser + e.ExportReqURLPattern = n.ExportReqURLPattern + e.GlobalMatchers = n.GlobalMatchers + e.Logger = n.Logger + e.CustomFastdialer = n.CustomFastdialer } diff --git a/pkg/protocols/whois/rdapclientpool/clientpool.go b/pkg/protocols/whois/rdapclientpool/clientpool.go index 81da1c578..f2d4f2316 100644 --- a/pkg/protocols/whois/rdapclientpool/clientpool.go +++ b/pkg/protocols/whois/rdapclientpool/clientpool.go @@ -30,6 +30,12 @@ func Init(options *types.Options) error { return nil } +func getNormalClient() *rdap.Client { + m.Lock() + defer m.Unlock() + return normalClient +} + // Configuration contains the custom configuration options for a client - placeholder type Configuration struct{} @@ -40,7 +46,5 @@ func (c *Configuration) Hash() string { // Get creates or gets a client for the protocol based on custom configuration func Get(options *types.Options, configuration *Configuration) (*rdap.Client, error) { - m.Lock() - defer m.Unlock() - return normalClient, nil + return getNormalClient(), nil } diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index a0d99a768..fdb612a96 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -56,49 +56,90 @@ func Parse(filePath string, preprocessor Preprocessor, options *protocols.Execut } if !options.DoNotCache { if value, _, _ := parser.compiledTemplatesCache.Has(filePath); value != nil { - // Update the template to use the current options for the calling engine - // TODO: This may be require additional work for robustness - t := *value - t.Options.ApplyNewEngineOptions(options) - if t.CompiledWorkflow != nil { - t.CompiledWorkflow.Options.ApplyNewEngineOptions(options) - for _, w := range t.CompiledWorkflow.Workflows { + // Copy the template, apply new options, and recompile requests + tplCopy := *value + newBase := options.Copy() + newBase.TemplateID = tplCopy.Options.TemplateID + newBase.TemplatePath = tplCopy.Options.TemplatePath + newBase.TemplateInfo = tplCopy.Options.TemplateInfo + newBase.TemplateVerifier = tplCopy.Options.TemplateVerifier + newBase.RawTemplate = tplCopy.Options.RawTemplate + tplCopy.Options = newBase + + tplCopy.Options.ApplyNewEngineOptions(options) + if tplCopy.CompiledWorkflow != nil { + tplCopy.CompiledWorkflow.Options.ApplyNewEngineOptions(options) + for _, w := range tplCopy.CompiledWorkflow.Workflows { for _, ex := range w.Executers { ex.Options.ApplyNewEngineOptions(options) } } } - for _, r := range t.RequestsDNS { - r.UpdateOptions(t.Options) + + // TODO: Reconsider whether to recompile requests. Compiling these is just as slow + // as not using a cache at all, but may be necessary. + + for i, r := range tplCopy.RequestsDNS { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsDNS[i] = &rCopy } - for _, r := range t.RequestsHTTP { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsHTTP { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsHTTP[i] = &rCopy } - for _, r := range t.RequestsCode { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsCode { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsCode[i] = &rCopy } - for _, r := range t.RequestsFile { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsFile { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsFile[i] = &rCopy } - for _, r := range t.RequestsHeadless { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsHeadless { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsHeadless[i] = &rCopy } - for _, r := range t.RequestsNetwork { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsNetwork { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsNetwork[i] = &rCopy } - for _, r := range t.RequestsJavascript { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsJavascript { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + //rCopy.Compile(tplCopy.Options) + tplCopy.RequestsJavascript[i] = &rCopy } - for _, r := range t.RequestsSSL { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsSSL { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsSSL[i] = &rCopy } - for _, r := range t.RequestsWHOIS { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsWHOIS { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsWHOIS[i] = &rCopy } - for _, r := range t.RequestsWebsocket { - r.UpdateOptions(t.Options) + for i, r := range tplCopy.RequestsWebsocket { + rCopy := *r + rCopy.UpdateOptions(tplCopy.Options) + // rCopy.Compile(tplCopy.Options) + tplCopy.RequestsWebsocket[i] = &rCopy } - template := t + template := &tplCopy if template.isGlobalMatchersEnabled() { item := &globalmatchers.Item{ @@ -119,8 +160,8 @@ func Parse(filePath string, preprocessor Preprocessor, options *protocols.Execut template.CompiledWorkflow = compiled template.CompiledWorkflow.Options = options } - - return &template, nil + // options.Logger.Error().Msgf("returning cached template %s after recompiling %d requests", tplCopy.Options.TemplateID, tplCopy.Requests()) + return template, nil } } diff --git a/pkg/templates/parser.go b/pkg/templates/parser.go index b99529916..56b64c237 100644 --- a/pkg/templates/parser.go +++ b/pkg/templates/parser.go @@ -49,6 +49,23 @@ func (p *Parser) Cache() *Cache { return p.parsedTemplatesCache } +// CompiledCache returns the compiled templates cache +func (p *Parser) CompiledCache() *Cache { + return p.compiledTemplatesCache +} + +func (p *Parser) ParsedCount() int { + p.Lock() + defer p.Unlock() + return len(p.parsedTemplatesCache.items.Map) +} + +func (p *Parser) CompiledCount() int { + p.Lock() + defer p.Unlock() + return len(p.compiledTemplatesCache.items.Map) +} + func checkOpenFileError(err error) bool { if err != nil && strings.Contains(err.Error(), "too many open files") { panic(err) @@ -171,84 +188,3 @@ func (p *Parser) LoadWorkflow(templatePath string, catalog catalog.Catalog) (boo return false, nil } - -// CloneForExecutionId creates a clone with updated execution IDs -func (p *Parser) CloneForExecutionId(xid string) *Parser { - p.Lock() - defer p.Unlock() - - newParser := &Parser{ - ShouldValidate: p.ShouldValidate, - NoStrictSyntax: p.NoStrictSyntax, - parsedTemplatesCache: NewCache(), - compiledTemplatesCache: NewCache(), - } - - for k, tpl := range p.parsedTemplatesCache.items.Map { - newTemplate := templateUpdateExecutionId(tpl.template, xid) - newParser.parsedTemplatesCache.Store(k, newTemplate, []byte(tpl.raw), tpl.err) - } - - for k, tpl := range p.compiledTemplatesCache.items.Map { - newTemplate := templateUpdateExecutionId(tpl.template, xid) - newParser.compiledTemplatesCache.Store(k, newTemplate, []byte(tpl.raw), tpl.err) - } - - return newParser -} - -func templateUpdateExecutionId(tpl *Template, xid string) *Template { - // TODO: This is a no-op today since options are patched in elsewhere, but we're keeping this - // for future work where we may need additional tweaks per template instance. - return tpl - - /* - templateBase := *tpl - var newOpts *protocols.ExecutorOptions - // Swap out the types.Options execution ID attached to the template - if templateBase.Options != nil { - optionsBase := *templateBase.Options //nolint - templateBase.Options = &optionsBase - if templateBase.Options.Options != nil { - optionsOptionsBase := *templateBase.Options.Options //nolint - templateBase.Options.Options = &optionsOptionsBase - templateBase.Options.Options.ExecutionId = xid - newOpts = templateBase.Options - } - } - if newOpts == nil { - return &templateBase - } - for _, r := range templateBase.RequestsDNS { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsHTTP { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsCode { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsFile { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsHeadless { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsNetwork { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsJavascript { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsSSL { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsWHOIS { - r.UpdateOptions(newOpts) - } - for _, r := range templateBase.RequestsWebsocket { - r.UpdateOptions(newOpts) - } - return &templateBase - */ -} diff --git a/pkg/utils/capture_writer.go b/pkg/utils/capture_writer.go new file mode 100644 index 000000000..29986a5aa --- /dev/null +++ b/pkg/utils/capture_writer.go @@ -0,0 +1,16 @@ +package utils + +import ( + "bytes" + + "github.com/projectdiscovery/gologger/levels" +) + +// CaptureWriter captures log output for testing +type CaptureWriter struct { + Buffer *bytes.Buffer +} + +func (w *CaptureWriter) Write(data []byte, level levels.Level) { + w.Buffer.Write(data) +} From 05f69a6b24f106a8ea0867d9ec9225b959f286f7 Mon Sep 17 00:00:00 2001 From: Ice3man Date: Sat, 19 Jul 2025 00:11:25 +0530 Subject: [PATCH 064/135] feat: log event for template host skipped during scanning (#6324) * feat: log event for template host skipped during scanning * misc changes --- pkg/core/executors.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pkg/core/executors.go b/pkg/core/executors.go index 05430233b..424b8c50a 100644 --- a/pkg/core/executors.go +++ b/pkg/core/executors.go @@ -4,9 +4,11 @@ import ( "context" "sync" "sync/atomic" + "time" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/input/provider" + "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs" "github.com/projectdiscovery/nuclei/v3/pkg/scan" "github.com/projectdiscovery/nuclei/v3/pkg/templates" @@ -108,6 +110,22 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ // Skip if the host has had errors if e.executerOpts.HostErrorsCache != nil && e.executerOpts.HostErrorsCache.Check(e.executerOpts.ProtocolType.String(), contextargs.NewWithMetaInput(ctx, scannedValue)) { + skipEvent := &output.ResultEvent{ + TemplateID: template.ID, + TemplatePath: template.Path, + Info: template.Info, + Type: e.executerOpts.ProtocolType.String(), + Host: scannedValue.Input, + MatcherStatus: false, + Error: "host was skipped as it was found unresponsive", + Timestamp: time.Now(), + } + + if e.Callback != nil { + e.Callback(skipEvent) + } else if e.executerOpts.Output != nil { + _ = e.executerOpts.Output.Write(skipEvent) + } return true } From 9133e0d2d0ec60637a421ab4c2faad100067a339 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 19 Jul 2025 01:42:50 +0700 Subject: [PATCH 065/135] 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 * chore(chore): i meant highest level Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- pkg/protocols/code/code.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index ef653ff13..4af590c77 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -94,9 +94,31 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { engine, err := gozero.New(gozeroOptions) if err != nil { - return errorutil.NewWithErr(err).Msgf("[%s] engines '%s' not available on host", options.TemplateID, strings.Join(request.Engine, ",")) + errMsg := fmt.Sprintf("[%s] engines '%s' not available on host", options.TemplateID, strings.Join(request.Engine, ",")) + + // NOTE(dwisiswant0): In validation mode, skip engine avail check to + // allow template validation w/o requiring all engines to be installed + // on the host. + // + // TODO: Ideally, error checking should be done at the highest level + // (e.g. runner, main function). For example, we can reuse errors[1][2] + // from the `projectdiscovery/gozero` package and wrap (yes, not string + // format[3][4]) em inside `projectdiscovery/utils/errors` package to + // preserve error semantics and enable runtime type assertion via + // builtin `errors.Is` func for granular err handling in the call stack. + // + // [1]: https://github.com/projectdiscovery/gozero/blob/v0.0.3/gozero.go#L20 + // [2]: https://github.com/projectdiscovery/gozero/blob/v0.0.3/gozero.go#L35 + // [3]: https://github.com/projectdiscovery/utils/blob/v0.4.21/errors/enriched.go#L85 + // [4]: https://github.com/projectdiscovery/utils/blob/v0.4.21/errors/enriched.go#L137 + if options.Options.Validate { + options.Logger.Error().Msgf("%s <- %s", errMsg, err) + } else { + return errorutil.NewWithErr(err).Msgf(errMsg) + } + } else { + request.gozero = engine } - request.gozero = engine var src *gozero.Source From 0337b33490a54e5ed31e35782bb763cf07e98453 Mon Sep 17 00:00:00 2001 From: jishudashen Date: Mon, 21 Jul 2025 14:13:22 +0800 Subject: [PATCH 066/135] chore: fix inconsistent function name in comment Signed-off-by: jishudashen --- pkg/protocols/protocols.go | 2 +- pkg/protocols/utils/http/requtils.go | 2 +- pkg/templates/signer/handler.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/protocols/protocols.go b/pkg/protocols/protocols.go index 197d79e0a..702aa5729 100644 --- a/pkg/protocols/protocols.go +++ b/pkg/protocols/protocols.go @@ -157,7 +157,7 @@ func (e *ExecutorOptions) RateLimitTake() { } } -// GetThreadsForPayloadRequests returns the number of threads to use as default for +// GetThreadsForNPayloadRequests returns the number of threads to use as default for // given max-request of payloads func (e *ExecutorOptions) GetThreadsForNPayloadRequests(totalRequests int, currentThreads int) int { if currentThreads > 0 { diff --git a/pkg/protocols/utils/http/requtils.go b/pkg/protocols/utils/http/requtils.go index 79e980bb7..bfc602a05 100644 --- a/pkg/protocols/utils/http/requtils.go +++ b/pkg/protocols/utils/http/requtils.go @@ -35,7 +35,7 @@ func UpdateURLPortFromPayload(parsed *urlutil.URL, data string) (*urlutil.URL, s return parsed, data } -// setHeader sets some headers only if the header wasn't supplied by the user +// SetHeader sets some headers only if the header wasn't supplied by the user func SetHeader(req *retryablehttp.Request, name, value string) { if _, ok := req.Header[name]; !ok { req.Header.Set(name, value) diff --git a/pkg/templates/signer/handler.go b/pkg/templates/signer/handler.go index 860719143..a263b181a 100644 --- a/pkg/templates/signer/handler.go +++ b/pkg/templates/signer/handler.go @@ -46,7 +46,7 @@ type KeyHandler struct { ecdsaKey *ecdsa.PrivateKey } -// ReadUserCert reads the user certificate from environment variable or given directory +// ReadCert reads the user certificate from environment variable or given directory func (k *KeyHandler) ReadCert(envName, dir string) error { // read from env if cert := k.getEnvContent(envName); cert != nil { From 91adfeb91c2e8fe1e077dd5f36c045442c18009c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0tefan=20Baebler?= <319826+stefanb@users.noreply.github.com> Date: Mon, 28 Jul 2025 14:46:44 +0200 Subject: [PATCH 067/135] 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/sonic@v1.14.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 --------- Signed-off-by: Dwi Siswanto Co-authored-by: Dwi Siswanto --- go.mod | 4 ++-- go.sum | 8 ++++---- pkg/utils/json/doc.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 99539206c..400503937 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.17.70 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82 github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 - github.com/bytedance/sonic v1.13.3 + github.com/bytedance/sonic v1.14.0 github.com/cespare/xxhash v1.1.0 github.com/charmbracelet/glamour v0.10.0 github.com/clbanning/mxj/v2 v2.7.0 @@ -169,7 +169,7 @@ require ( github.com/bodgit/sevenzip v1.6.0 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect - github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/caddyserver/certmagic v0.19.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect diff --git a/go.sum b/go.sum index 13329fc0e..83ee118a8 100644 --- a/go.sum +++ b/go.sum @@ -216,11 +216,11 @@ github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0 github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0= -github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= -github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0= github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= diff --git a/pkg/utils/json/doc.go b/pkg/utils/json/doc.go index b9cc45cfd..6cee2e742 100644 --- a/pkg/utils/json/doc.go +++ b/pkg/utils/json/doc.go @@ -1,7 +1,7 @@ // Package json provides fast JSON encoding and decoding functionality. // // On supported platforms; Linux, Darwin, or Windows on amd64, or on arm64 with -// Go >= 1.20 and <= 1.24, the package uses the high-performance [sonic] library. +// Go >= 1.20 and <= 1.25, the package uses the high-performance [sonic] library. // On any other systems, it gracefully falls back to using the [go-json] // implementation. // From 06707ea76fe2b5503ef504dd1e71fd2788ae2299 Mon Sep 17 00:00:00 2001 From: Ice3man Date: Wed, 30 Jul 2025 21:38:07 +0530 Subject: [PATCH 068/135] bugfix: preserve original transport for linear http client (#6357) --- pkg/reporting/trackers/linear/linear.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/reporting/trackers/linear/linear.go b/pkg/reporting/trackers/linear/linear.go index 24b464f33..be8723368 100644 --- a/pkg/reporting/trackers/linear/linear.go +++ b/pkg/reporting/trackers/linear/linear.go @@ -54,15 +54,17 @@ type Options struct { // New creates a new issue tracker integration client based on options. func New(options *Options) (*Integration, error) { + var transport http.RoundTripper = http.DefaultTransport + if options.HttpClient != nil && options.HttpClient.HTTPClient.Transport != nil { + transport = options.HttpClient.HTTPClient.Transport + } + httpClient := &http.Client{ Transport: &addHeaderTransport{ - T: http.DefaultTransport, + T: transport, Key: options.APIKey, }, } - if options.HttpClient != nil { - httpClient.Transport = options.HttpClient.HTTPClient.Transport - } integration := &Integration{ url: "https://api.linear.app/graphql", @@ -385,8 +387,8 @@ func (i *Integration) doGraphqlRequest(ctx context.Context, query string, v any, return err } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("non-200 OK status code: %v body: %q", resp.Status, body) From 3ac3146ef9df38eb081bcb6f2f033ca65df8299c Mon Sep 17 00:00:00 2001 From: poning Date: Fri, 1 Aug 2025 15:35:03 -0700 Subject: [PATCH 069/135] 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 --------- Signed-off-by: Dwi Siswanto Co-authored-by: Dwi Siswanto --- pkg/protocols/offlinehttp/operators.go | 2 +- pkg/protocols/offlinehttp/operators_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/protocols/offlinehttp/operators.go b/pkg/protocols/offlinehttp/operators.go index cbce83cb6..3164c086a 100644 --- a/pkg/protocols/offlinehttp/operators.go +++ b/pkg/protocols/offlinehttp/operators.go @@ -109,7 +109,7 @@ func (request *Request) responseToDSLMap(resp *http.Response, host, matched, raw data[strings.ToLower(cookie.Name)] = cookie.Value } for k, v := range resp.Header { - k = strings.ToLower(strings.TrimSpace(k)) + k = strings.ToLower(strings.ReplaceAll(strings.TrimSpace(k), "-", "_")) data[k] = strings.Join(v, " ") } diff --git a/pkg/protocols/offlinehttp/operators_test.go b/pkg/protocols/offlinehttp/operators_test.go index 21bb86939..4fb8c39f7 100644 --- a/pkg/protocols/offlinehttp/operators_test.go +++ b/pkg/protocols/offlinehttp/operators_test.go @@ -134,7 +134,7 @@ func TestHTTPOperatorExtract(t *testing.T) { event := request.responseToDSLMap(resp, host, matched, exampleRawRequest, exampleRawResponse, exampleResponseBody, exampleResponseHeader, 1*time.Second, map[string]interface{}{}) require.Len(t, event, 14, "could not get correct number of items in dsl map") require.Equal(t, exampleRawResponse, event["response"], "could not get correct resp") - require.Equal(t, "Test-Response", event["test-header"], "could not get correct resp for header") + require.Equal(t, "Test-Response", event["test_header"], "could not get correct resp for header") t.Run("extract", func(t *testing.T) { extractor := &extractors.Extractor{ @@ -153,7 +153,7 @@ func TestHTTPOperatorExtract(t *testing.T) { t.Run("kval", func(t *testing.T) { extractor := &extractors.Extractor{ Type: extractors.ExtractorTypeHolder{ExtractorType: extractors.KValExtractor}, - KVal: []string{"test-header"}, + KVal: []string{"test_header"}, Part: "header", } err = extractor.CompileExtractors() From 5ba21e272a6b258c9c438ccfa7081b07c4ef0ef8 Mon Sep 17 00:00:00 2001 From: Ice3man Date: Sat, 2 Aug 2025 15:54:15 +0530 Subject: [PATCH 070/135] feat: loading templates performance improvements --- internal/runner/options.go | 5 ++-- pkg/operators/matchers/validate.go | 23 +++++++++++------- pkg/templates/parser.go | 36 ++++++++++++++++++++-------- pkg/templates/templates.go | 13 ++++------ pkg/templates/validator_singleton.go | 7 ++++++ 5 files changed, 56 insertions(+), 28 deletions(-) create mode 100644 pkg/templates/validator_singleton.go diff --git a/internal/runner/options.go b/internal/runner/options.go index 57b28973b..cd071e2d5 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -40,6 +40,8 @@ const ( DefaultDumpTrafficOutputFolder = "output" ) +var validateOptions = validator.New() + func ConfigureOptions() error { // with FileStringSliceOptions, FileNormalizedStringSliceOptions, FileCommaSeparatedStringSliceOptions // if file has the extension `.yaml` or `.json` we consider those as strings and not files to be read @@ -139,8 +141,7 @@ func ParseOptions(options *types.Options) { // validateOptions validates the configuration options passed func ValidateOptions(options *types.Options) error { - validate := validator.New() - if err := validate.Struct(options); err != nil { + if err := validateOptions.Struct(options); err != nil { if _, ok := err.(*validator.InvalidValidationError); ok { return err } diff --git a/pkg/operators/matchers/validate.go b/pkg/operators/matchers/validate.go index 0f6a5b916..7dd5a1388 100644 --- a/pkg/operators/matchers/validate.go +++ b/pkg/operators/matchers/validate.go @@ -8,22 +8,29 @@ import ( "github.com/antchfx/xpath" sliceutil "github.com/projectdiscovery/utils/slice" - "gopkg.in/yaml.v3" ) var commonExpectedFields = []string{"Type", "Condition", "Name", "MatchAll", "Negative", "Internal"} // Validate perform initial validation on the matcher structure func (matcher *Matcher) Validate() error { - // uses yaml marshaling to convert the struct to map[string]interface to have same field names + // Build a map of YAML‐tag names that are actually set (non-zero) in the matcher. matcherMap := make(map[string]interface{}) - marshaledMatcher, err := yaml.Marshal(matcher) - if err != nil { - return err - } - if err := yaml.Unmarshal(marshaledMatcher, &matcherMap); err != nil { - return err + val := reflect.ValueOf(*matcher) + typ := reflect.TypeOf(*matcher) + for i := 0; i < typ.NumField(); i++ { + field := typ.Field(i) + // skip internal / unexported or opt-out fields + yamlTag := strings.Split(field.Tag.Get("yaml"), ",")[0] + if yamlTag == "" || yamlTag == "-" { + continue + } + if val.Field(i).IsZero() { + continue + } + matcherMap[yamlTag] = struct{}{} } + var err error var expectedFields []string switch matcher.matcherType { diff --git a/pkg/templates/parser.go b/pkg/templates/parser.go index 7f481dc85..626b05319 100644 --- a/pkg/templates/parser.go +++ b/pkg/templates/parser.go @@ -100,13 +100,13 @@ func (p *Parser) ParseTemplate(templatePath string, catalog catalog.Catalog) (an _ = reader.Close() }() - data, err := io.ReadAll(reader) - if err != nil { - return nil, err - } - - // pre-process directives only for local files + // For local YAML files, check if preprocessing is needed + var data []byte if fileutil.FileExists(templatePath) && config.GetTemplateFormatFromExt(templatePath) == config.YAML { + data, err = io.ReadAll(reader) + if err != nil { + return nil, err + } data, err = yamlutil.PreProcess(data) if err != nil { return nil, err @@ -117,12 +117,28 @@ func (p *Parser) ParseTemplate(templatePath string, catalog catalog.Catalog) (an switch config.GetTemplateFormatFromExt(templatePath) { case config.JSON: + if data == nil { + data, err = io.ReadAll(reader) + if err != nil { + return nil, err + } + } err = json.Unmarshal(data, template) case config.YAML: - if p.NoStrictSyntax { - err = yaml.Unmarshal(data, template) + if data != nil { + // Already read and preprocessed + if p.NoStrictSyntax { + err = yaml.Unmarshal(data, template) + } else { + err = yaml.UnmarshalStrict(data, template) + } } else { - err = yaml.UnmarshalStrict(data, template) + // Stream directly from reader + decoder := yaml.NewDecoder(reader) + if !p.NoStrictSyntax { + decoder.SetStrict(true) + } + err = decoder.Decode(template) } default: err = fmt.Errorf("failed to identify template format expected JSON or YAML but got %v", templatePath) @@ -131,7 +147,7 @@ func (p *Parser) ParseTemplate(templatePath string, catalog catalog.Catalog) (an return nil, err } - p.parsedTemplatesCache.Store(templatePath, template, data, nil) + p.parsedTemplatesCache.Store(templatePath, template, nil, nil) // don't keep raw bytes to save memory return template, nil } diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index 7726fc7c9..fbbfd44e9 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" - validate "github.com/go-playground/validator/v10" "github.com/projectdiscovery/nuclei/v3/pkg/model" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/code" @@ -310,10 +309,8 @@ func (template *Template) validateAllRequestIDs() { // MarshalYAML forces recursive struct validation during marshal operation func (template *Template) MarshalYAML() ([]byte, error) { out, marshalErr := yaml.Marshal(template) - // Review: we are adding requestIDs for templateContext - // if we are using this method then we might need to purge manually added IDS that start with `templatetype_` - // this is only applicable if there are more than 1 request fields in protocol - errValidate := validate.New().Struct(template) + // Use shared validator to avoid rebuilding struct cache for every template marshal + errValidate := tplValidator.Struct(template) return out, multierr.Append(marshalErr, errValidate) } @@ -354,7 +351,7 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error if len(alias.RequestsWithTCP) > 0 { template.RequestsNetwork = alias.RequestsWithTCP } - err = validate.New().Struct(template) + err = tplValidator.Struct(template) if err != nil { return err } @@ -525,7 +522,7 @@ func (template *Template) hasMultipleRequests() bool { func (template *Template) MarshalJSON() ([]byte, error) { type TemplateAlias Template //avoid recursion out, marshalErr := json.Marshal((*TemplateAlias)(template)) - errValidate := validate.New().Struct(template) + errValidate := tplValidator.Struct(template) return out, multierr.Append(marshalErr, errValidate) } @@ -538,7 +535,7 @@ func (template *Template) UnmarshalJSON(data []byte) error { return err } *template = Template(*alias) - err = validate.New().Struct(template) + err = tplValidator.Struct(template) if err != nil { return err } diff --git a/pkg/templates/validator_singleton.go b/pkg/templates/validator_singleton.go new file mode 100644 index 000000000..9679ac210 --- /dev/null +++ b/pkg/templates/validator_singleton.go @@ -0,0 +1,7 @@ +package templates + +import ( + validate "github.com/go-playground/validator/v10" +) + +var tplValidator = validate.New() From 3d7f995ddcc9986854cf806199eb0bace8a7de5a Mon Sep 17 00:00:00 2001 From: Ice3man Date: Sun, 3 Aug 2025 03:53:34 +0530 Subject: [PATCH 071/135] use bounded concurrency for templates loading --- pkg/catalog/loader/loader.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 98039117d..33c5e226f 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -7,7 +7,8 @@ import ( "os" "sort" "strings" - "sync" + + syncutil "github.com/projectdiscovery/utils/sync" "github.com/logrusorgru/aurora" "github.com/pkg/errors" @@ -238,8 +239,8 @@ func (store *Store) ReadTemplateFromURI(uri string, remote bool) ([]byte, error) return nil, err } defer func() { - _ = resp.Body.Close() - }() + _ = resp.Body.Close() + }() return io.ReadAll(resp.Body) } else { return os.ReadFile(uri) @@ -502,10 +503,15 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ } } - var wgLoadTemplates sync.WaitGroup + // Use adaptive wait-group to cap concurrent loaders and auto-scale with demand. + maxConcurrency := store.config.ExecutorOptions.Options.TemplateThreads + if maxConcurrency <= 0 { + maxConcurrency = 25 + } + wgLoadTemplates, _ := syncutil.New(syncutil.WithSize(maxConcurrency)) for templatePath := range templatePathMap { - wgLoadTemplates.Add(1) + wgLoadTemplates.Add() go func(templatePath string) { defer wgLoadTemplates.Done() From cff86b5c98255615ec79341b4cf50a2861b121e0 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sun, 3 Aug 2025 11:49:48 +0700 Subject: [PATCH 072/135] fix(events): correct JSON encoder type in `ScanStatsWorker` (#6366) Signed-off-by: Dwi Siswanto --- pkg/scan/events/stats_build.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/scan/events/stats_build.go b/pkg/scan/events/stats_build.go index 41901cc5a..7d03e42e5 100644 --- a/pkg/scan/events/stats_build.go +++ b/pkg/scan/events/stats_build.go @@ -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 From b685d637f3af21feec1fbd3f560d0a863db4e013 Mon Sep 17 00:00:00 2001 From: knakul853 Date: Mon, 4 Aug 2025 21:12:43 +0530 Subject: [PATCH 073/135] fix: prevent nil pointer panic in WAF detector - Add nil checks for detector and regexCache in DetectWAF() - Add nil check for individual regex entries before MatchString() - Add comprehensive unit tests for nil pointer scenarios - Prevents runtime panic when WAF detector encounters nil pointers during regex matching --- pkg/output/stats/waf/waf.go | 6 ++- pkg/output/stats/waf/waf_test.go | 63 +++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/pkg/output/stats/waf/waf.go b/pkg/output/stats/waf/waf.go index a660ff7b1..7abe68cab 100644 --- a/pkg/output/stats/waf/waf.go +++ b/pkg/output/stats/waf/waf.go @@ -53,8 +53,12 @@ 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.MatchString(content) { + if regex != nil && regex.MatchString(content) { return id, true } } diff --git a/pkg/output/stats/waf/waf_test.go b/pkg/output/stats/waf/waf_test.go index 0698b3a42..f3b2b8683 100644 --- a/pkg/output/stats/waf/waf_test.go +++ b/pkg/output/stats/waf/waf_test.go @@ -1,6 +1,9 @@ package waf -import "testing" +import ( + "regexp" + "testing" +) func TestWAFDetection(t *testing.T) { detector := NewWafDetector() @@ -58,3 +61,61 @@ 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) + } + }) + } +} From 6996b4ab7573e7bb5f78a596a5cc52fd8acb21f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Wed, 13 Aug 2025 19:22:34 -0700 Subject: [PATCH 074/135] bump version --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index 15d8e9dae..5d4a4a0d2 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.7` + Version = `v3.4.8` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From 7e95d9a1853c0d769ed168daff15b4bb0f86e745 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Fri, 15 Aug 2025 07:35:51 +0700 Subject: [PATCH 075/135] build(make): update `template-validate` cmds (#6385) Signed-off-by: Dwi Siswanto --- Makefile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0c3ab083b..1b089e76f 100644 --- a/Makefile +++ b/Makefile @@ -146,5 +146,14 @@ dsl-docs: template-validate: build template-validate: ./bin/nuclei -ut - ./bin/nuclei -validate -et http/technologies - ./bin/nuclei -validate -w workflows -et http/technologies \ No newline at end of file + ./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 \ No newline at end of file From 89de8a5a59bc29685d4dd69001851465934fb756 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 14:48:58 +0000 Subject: [PATCH 076/135] chore(deps): bump the go_modules group across 1 directory with 2 updates Bumps the go_modules group with 2 updates in the / directory: [github.com/docker/docker](https://github.com/docker/docker) and [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure). Updates `github.com/docker/docker` from 27.1.1+incompatible to 28.0.0+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.1...v28.0.0) Updates `github.com/go-viper/mapstructure/v2` from 2.2.1 to 2.3.0 - [Release notes](https://github.com/go-viper/mapstructure/releases) - [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md) - [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-version: 28.0.0+incompatible dependency-type: indirect dependency-group: go_modules - dependency-name: github.com/go-viper/mapstructure/v2 dependency-version: 2.3.0 dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 400503937..71ab9060b 100644 --- a/go.mod +++ b/go.mod @@ -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 v27.1.1+incompatible // indirect + github.com/docker/docker v28.0.0+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 @@ -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.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.3.0 // 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 diff --git a/go.sum b/go.sum index 83ee118a8..a8e3dcb99 100644 --- a/go.sum +++ b/go.sum @@ -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 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/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/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= @@ -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.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +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/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= From d569cfe8644f97ca7b9c02c2db11ac0aca495a8e Mon Sep 17 00:00:00 2001 From: ysokolovsky Date: Sat, 16 Aug 2025 01:18:34 +0200 Subject: [PATCH 077/135] fix(headless): merge extra headers (#6376) * headless: fix extra headers overwrite * headless: set Accept-Language when no custom headers --- pkg/protocols/headless/engine/engine.go | 46 +++++++++++++++++++++---- pkg/protocols/headless/engine/page.go | 8 ++--- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/pkg/protocols/headless/engine/engine.go b/pkg/protocols/headless/engine/engine.go index 63dbb41ef..998850237 100644 --- a/pkg/protocols/headless/engine/engine.go +++ b/pkg/protocols/headless/engine/engine.go @@ -20,12 +20,13 @@ import ( // Browser is a browser structure for nuclei headless module type Browser struct { - customAgent string - tempDir string - previousPIDs map[int32]struct{} // track already running PIDs - engine *rod.Browser - options *types.Options - launcher *launcher.Launcher + 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 // use getHTTPClient to get the http client httpClient *http.Client @@ -95,6 +96,7 @@ 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) @@ -103,12 +105,20 @@ 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{}, @@ -135,6 +145,30 @@ 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() { diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index 6986f80b4..244d740c8 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -61,6 +61,10 @@ 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 @@ -130,10 +134,6 @@ 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 From 70eeb6c210b12988b0f95ebb06c20893201a486f Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 16 Aug 2025 06:20:20 +0700 Subject: [PATCH 078/135] fix: prevent unnecessary template updates (#6379) * test(installer): adds `TestIsOutdatedVersionFix` Signed-off-by: Dwi Siswanto * fix: prevent unnecessary template updates when version API fails. * fix `catalog/config.IsOutdatedVersion` logic for empty version strings * add GitHub API fallback when PDTM API is unavail * only show outdated msg for actual version mismatches Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- pkg/catalog/config/constants.go | 15 ++++++++----- pkg/installer/template.go | 28 +++++++++++++++++++++-- pkg/installer/template_test.go | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index 5d4a4a0d2..a9de026d8 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -46,18 +46,21 @@ const ( // if the current version is outdated func IsOutdatedVersion(current, latest string) bool { if latest == "" { - // 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 + // 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 } + current = trimDevIfExists(current) currentVer, _ := semver.NewVersion(current) newVer, _ := semver.NewVersion(latest) + if currentVer == nil || newVer == nil { - // fallback to naive comparison - return current == latest + // fallback to naive comparison - return true only if they are different + return current != latest } + return newVer.GreaterThan(currentVer) } diff --git a/pkg/installer/template.go b/pkg/installer/template.go index 9e56f12a1..d9f3d5ae1 100644 --- a/pkg/installer/template.go +++ b/pkg/installer/template.go @@ -94,7 +94,24 @@ func (t *TemplateManager) UpdateIfOutdated() error { if !fileutil.FolderExists(config.DefaultConfig.TemplatesDirectory) { return t.FreshInstallIfNotExists() } - if config.DefaultConfig.NeedsTemplateUpdate() { + + 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 { return t.updateTemplatesAt(config.DefaultConfig.TemplatesDirectory) } return nil @@ -142,7 +159,14 @@ func (t *TemplateManager) updateTemplatesAt(dir string) error { return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir) } - gologger.Info().Msgf("Your current nuclei-templates %s are outdated. Latest is %s\n", config.DefaultConfig.TemplateVersion, ghrd.Latest.GetTagName()) + 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) + } // write templates to disk if err := t.writeTemplatesToDisk(ghrd, dir); err != nil { diff --git a/pkg/installer/template_test.go b/pkg/installer/template_test.go index 952c44596..435797b1f 100644 --- a/pkg/installer/template_test.go +++ b/pkg/installer/template_test.go @@ -59,3 +59,42 @@ 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) + }) + } +} From 9fcacd0f86c1ed7e39ee2ee4ce8f158b2805670c Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 16 Aug 2025 13:20:09 +0700 Subject: [PATCH 079/135] ci(tests): migrate to golangci-lint v2 (#6380) * chore: satisfy lints Signed-off-by: Dwi Siswanto * ci(tests): migrate to golangci-lint v2 Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- .github/workflows/tests.yaml | 2 +- pkg/protocols/headless/engine/engine.go | 2 +- pkg/reporting/trackers/linear/linear.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index dce907afb..f8297c107 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -24,7 +24,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: projectdiscovery/actions/setup/go@v1 - - uses: projectdiscovery/actions/golangci-lint@v1 + - uses: projectdiscovery/actions/golangci-lint/v2@v1 tests: name: "Tests" diff --git a/pkg/protocols/headless/engine/engine.go b/pkg/protocols/headless/engine/engine.go index 998850237..c045580d6 100644 --- a/pkg/protocols/headless/engine/engine.go +++ b/pkg/protocols/headless/engine/engine.go @@ -181,6 +181,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) } diff --git a/pkg/reporting/trackers/linear/linear.go b/pkg/reporting/trackers/linear/linear.go index be8723368..75619c140 100644 --- a/pkg/reporting/trackers/linear/linear.go +++ b/pkg/reporting/trackers/linear/linear.go @@ -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.RoundTripper = http.DefaultTransport + var transport = http.DefaultTransport if options.HttpClient != nil && options.HttpClient.HTTPClient.Transport != nil { transport = options.HttpClient.HTTPClient.Transport } From 6a6fa4d38f801557053ec997bbc9625e24c71ac4 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 16 Aug 2025 16:11:22 +0700 Subject: [PATCH 080/135] feat(fuzz): eval variables (#6358) * feat(fuzz): eval vars for rule keys & values Signed-off-by: Dwi Siswanto * chore: re-fmt fuzzing/dast errors Signed-off-by: Dwi Siswanto * test(fuzz): adds `TestEvaluateVariables` Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- pkg/fuzz/execute.go | 70 ++++++++- pkg/fuzz/fuzz_test.go | 221 +++++++++++++++++++++++++++++ pkg/protocols/http/request_fuzz.go | 11 +- 3 files changed, 292 insertions(+), 10 deletions(-) diff --git a/pkg/fuzz/execute.go b/pkg/fuzz/execute.go index 8da89d0ea..eda78f4d0 100644 --- a/pkg/fuzz/execute.go +++ b/pkg/fuzz/execute.go @@ -14,6 +14,7 @@ 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" errorutil "github.com/projectdiscovery/utils/errors" @@ -23,7 +24,7 @@ import ( ) var ( - ErrRuleNotApplicable = errorutil.NewWithFmt("rule not applicable : %v") + ErrRuleNotApplicable = errorutil.NewWithFmt("rule not applicable: %v") ) // IsErrRuleNotApplicable checks if an error is due to rule not applicable @@ -189,6 +190,33 @@ 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 @@ -341,23 +369,47 @@ 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 { - rule.keysMap[strings.ToLower(key)] = struct{}{} + evaluatedKey, err := rule.evaluateVars(key) + if err != nil { + return errors.Wrap(err, "could not evaluate key") + } + + rule.keysMap[strings.ToLower(evaluatedKey)] = struct{}{} } + + // eval vars in "values" for _, value := range rule.ValuesRegex { - compiled, err := regexp.Compile(value) + evaluatedValue, err := rule.evaluateVars(value) + if err != nil { + return errors.Wrap(err, "could not evaluate value regex") + } + + compiled, err := regexp.Compile(evaluatedValue) 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 { - compiled, err := regexp.Compile(value) + evaluatedValue, err := rule.evaluateVars(value) + if err != nil { + return errors.Wrap(err, "could not evaluate key regex") + } + + compiled, err := regexp.Compile(evaluatedValue) 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") @@ -366,11 +418,19 @@ func (rule *Rule) Compile(generator *generators.PayloadGenerator, options *proto if rule.ReplaceRegex == "" { return errors.Errorf("replace-regex is required for replace-regex rule type") } - compiled, err := regexp.Compile(rule.ReplaceRegex) + + evalReplaceRegex, err := rule.evaluateVars(rule.ReplaceRegex) + if err != nil { + return errors.Wrap(err, "could not evaluate replace regex") + } + + compiled, err := regexp.Compile(evalReplaceRegex) if err != nil { return errors.Wrap(err, "could not compile replace regex") } + rule.replaceRegex = compiled } + return nil } diff --git a/pkg/fuzz/fuzz_test.go b/pkg/fuzz/fuzz_test.go index 6ef2e39b0..a4f5186c3 100644 --- a/pkg/fuzz/fuzz_test.go +++ b/pkg/fuzz/fuzz_test.go @@ -3,6 +3,11 @@ 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" ) @@ -37,3 +42,219 @@ 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") + } + }) +} diff --git a/pkg/protocols/http/request_fuzz.go b/pkg/protocols/http/request_fuzz.go index 045dec332..3a7e2cc74 100644 --- a/pkg/protocols/http/request_fuzz.go +++ b/pkg/protocols/http/request_fuzz.go @@ -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: rule not applicable : %s\n", request.options.TemplateID, err) + gologger.Verbose().Msgf("[%s] fuzz: %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: rule not applicable : %s\n", request.options.TemplateID, err) + gologger.Verbose().Msgf("[%s] fuzz: %s\n", request.options.TemplateID, err) continue } if err == types.ErrNoMoreRequests { @@ -168,8 +168,9 @@ func (request *Request) executeAllFuzzingRules(input *contextargs.Context, value } if !applicable { - return fuzz.ErrRuleNotApplicable.Msgf(fmt.Sprintf("no rule was applicable for this request: %v", input.MetaInput.Input)) + return fmt.Errorf("no rule was applicable for this request: %v", input.MetaInput.Input) } + return nil } From e1f8a18d38b6ced7fb14b27fee92e8348c379359 Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 16 Aug 2025 15:51:32 +0530 Subject: [PATCH 081/135] dep update + removed unused code --- cmd/nuclei/main.go | 7 ------- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index a44568af2..dd554a8a9 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -757,10 +757,3 @@ 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 - } -} diff --git a/go.mod b/go.mod index 71ab9060b..2fd4ee3b5 100644 --- a/go.mod +++ b/go.mod @@ -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.1 - github.com/projectdiscovery/hmap v0.0.91 + github.com/projectdiscovery/fastdialer v0.4.4 + github.com/projectdiscovery/hmap v0.0.92 github.com/projectdiscovery/interactsh v1.2.4 github.com/projectdiscovery/rawhttp v0.1.90 - github.com/projectdiscovery/retryabledns v1.0.103 - github.com/projectdiscovery/retryablehttp-go v1.0.117 + github.com/projectdiscovery/retryabledns v1.0.105 + github.com/projectdiscovery/retryablehttp-go v1.0.119 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.20250311103038-7794c8c0723b + github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39 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.17 + github.com/projectdiscovery/networkpolicy v0.1.18 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.21 + github.com/projectdiscovery/utils v0.4.23 github.com/projectdiscovery/wappalyzergo v0.2.36 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 @@ -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.4 // indirect + github.com/gaissmai/bart v0.20.5 // 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 @@ -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.0 // indirect + github.com/refraction-networking/utls v1.7.1 // 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 diff --git a/go.sum b/go.sum index a8e3dcb99..5fa540e33 100644 --- a/go.sum +++ b/go.sum @@ -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.4 h1:Ik47r1fy3jRVU+1eYzKSW3ho2UgBVTVnUS8O993584U= -github.com/gaissmai/bart v0.20.4/go.mod h1:cEed+ge8dalcbpi8wtS9x9m2hn/fNJH5suhdGQOHnYk= +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/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= @@ -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.1 h1:kp6Q0odo0VZ0vZIGOn+q9aLgBSk6uYoD1MsjCAH8+h4= -github.com/projectdiscovery/fastdialer v0.4.1/go.mod h1:875Wlggf0JAz+fDIPwUQeeBqEF6nJA71XVrjuTZCV7I= +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/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.91 h1:8vSTU+3hmMfA5Qd14ceq4j7wnUVUJcXdqQgqbsFBea0= -github.com/projectdiscovery/hmap v0.0.91/go.mod h1:BxEg8WXqxqaOADPZ+xp2X6BY+znfV8dusCSGSFnsU3c= +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/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.17 h1:A/axsarHnVgv8bPB2vuI/7Hg0PrFBL+KGFSurJlDzx0= -github.com/projectdiscovery/networkpolicy v0.1.17/go.mod h1:Bwgfqbb2RAMIQ0OvfVofoFQFV3DitnXZZX5DkQMnjx8= +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/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.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/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/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.21 h1:yAothTUSF6NwZ9yoC4iGe5gSBrovqKR9JwwW3msxk3Q= -github.com/projectdiscovery/utils v0.4.21/go.mod h1:HJuJFqjB6EmVaDl0ilFPKvLoMaX2GyE6Il2TqKXNs8I= +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/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.0 h1:9JTnze/Md74uS3ZWiRAabityY0un69rOLXsBf8LGgTs= -github.com/refraction-networking/utls v1.7.0/go.mod h1:lV0Gwc1/Fi+HYH8hOtgFRdHfKo4FKSn6+FdyOz9hRms= +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/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.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 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/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= From 44eeb5a60bd3285970ce0fdfd66586c5d4266aff Mon Sep 17 00:00:00 2001 From: Dogan Can Bakir <65292895+dogancanbakir@users.noreply.github.com> Date: Sat, 16 Aug 2025 13:20:22 -0700 Subject: [PATCH 082/135] enable templates for template listing and displaying (#6343) --- internal/runner/runner.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index b32f7e2f6..2a3c2c470 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -125,6 +125,14 @@ 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 { From b4644af80a574b6bf4af093310dcb239c9164190 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Wed, 20 Aug 2025 05:28:23 +0530 Subject: [PATCH 083/135] Lint + test fixes after utils dep update (#6393) * fix: remove undefined errorutil.ShowStackTrace * feat: add make lint support and integrate with test * refactor: migrate errorutil to errkit across codebase - Replace deprecated errorutil with modern errkit - Convert error declarations from var to func for better compatibility - Fix all SA1019 deprecation warnings - Maintain error chain support and stack traces * fix: improve DNS test reliability using Google DNS - Configure test to use Google DNS (8.8.8.8) for stability - Fix nil pointer issue in DNS client initialization - Keep production defaults unchanged * fixing logic * removing unwanted branches in makefile --------- Co-authored-by: Mzack9999 --- Makefile | 4 +- cmd/integration-test/http.go | 18 ++++---- cmd/integration-test/loader.go | 4 +- cmd/integration-test/profile-loader.go | 8 ++-- cmd/integration-test/template-dir.go | 4 +- cmd/nuclei/main.go | 4 +- cmd/tmc/main.go | 46 +++++++++---------- internal/pdcp/writer.go | 18 ++++---- internal/runner/lazy.go | 6 +-- internal/runner/proxy.go | 4 +- lib/config.go | 18 ++++---- lib/multi.go | 6 +-- lib/sdk.go | 20 ++++---- pkg/authprovider/authx/dynamic.go | 8 ++-- pkg/authprovider/authx/file.go | 6 +-- pkg/authprovider/file.go | 9 ++-- pkg/catalog/config/nucleiconfig.go | 20 ++++---- pkg/catalog/loader/ai_loader.go | 31 +++++++------ pkg/catalog/loader/loader.go | 4 +- pkg/external/customtemplates/azure_blob.go | 5 +- pkg/external/customtemplates/gitlab.go | 5 +- pkg/external/customtemplates/s3.go | 5 +- .../customtemplates/templates_provider.go | 10 ++-- pkg/fuzz/execute.go | 15 +++--- pkg/input/formats/openapi/generator.go | 18 ++++---- pkg/input/provider/interface.go | 10 ++-- pkg/installer/template.go | 35 +++++++------- pkg/installer/util.go | 4 +- pkg/js/devtools/tsgen/scrape.go | 8 ++-- pkg/js/global/scripts.go | 4 +- pkg/js/gojs/set.go | 9 ++-- pkg/js/libs/mssql/mssql.go | 6 +-- pkg/js/libs/mysql/mysql.go | 8 ++-- pkg/js/libs/net/net.go | 6 +-- pkg/js/libs/postgres/postgres.go | 4 +- pkg/js/libs/redis/redis.go | 8 ++-- pkg/js/libs/smb/smb.go | 6 +-- pkg/js/libs/smb/smbghost.go | 2 +- pkg/js/libs/smtp/smtp.go | 2 +- pkg/js/libs/ssh/ssh.go | 10 ++-- pkg/operators/common/dsl/dsl.go | 5 +- pkg/operators/common/dsl/dsl_test.go | 15 +++++- pkg/protocols/code/code.go | 7 ++- pkg/protocols/common/interactsh/interactsh.go | 10 ++-- pkg/protocols/common/protocolstate/file.go | 7 +-- .../common/protocolstate/headless.go | 22 +++++---- pkg/protocols/headless/engine/page.go | 4 +- pkg/protocols/headless/engine/page_actions.go | 27 ++++++----- pkg/protocols/http/build_request.go | 44 ++++++++++-------- pkg/protocols/http/raw/raw.go | 16 +++---- pkg/protocols/http/signer/aws-sign.go | 4 +- pkg/protocols/http/utils.go | 7 +-- pkg/protocols/javascript/js.go | 13 +++--- pkg/protocols/network/network.go | 7 +-- pkg/protocols/network/request.go | 4 +- pkg/protocols/ssl/ssl.go | 18 ++++---- .../exporters/markdown/util/markdown_utils.go | 6 +-- pkg/reporting/reporting.go | 28 +++++------ pkg/templates/compile.go | 6 +-- pkg/templates/parser.go | 8 ++-- pkg/templates/parser_error.go | 31 +++++++++---- pkg/templates/parser_test.go | 4 +- pkg/templates/parser_validate.go | 10 ++-- pkg/templates/signer/default.go | 4 +- pkg/templates/signer/tmpl_signer.go | 6 +-- pkg/templates/template_sign.go | 8 ++-- pkg/templates/templates.go | 17 +++---- pkg/tmplexec/flow/flow_executor.go | 16 +++---- pkg/tmplexec/flow/flow_internal.go | 2 +- pkg/types/types.go | 11 +++-- 70 files changed, 422 insertions(+), 363 deletions(-) diff --git a/Makefile b/Makefile index 1b089e76f..6aaa55de1 100644 --- a/Makefile +++ b/Makefile @@ -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 syntax-docs -.PHONY: integration jsupdate-all jsupdate-bindgen jsupdate-tsgen memogen scan-charts test +.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: tidy ts verify download vet template-validate all: build diff --git a/cmd/integration-test/http.go b/cmd/integration-test/http.go index 2d273d513..69fb35187 100644 --- a/cmd/integration-test/http.go +++ b/cmd/integration-test/http.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithErr(routerErr).Msgf("failed to send http request to interactsh server") + return errkit.Append(errkit.New("failed to send http request to interactsh server"), routerErr) } 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 = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value1"}, params["key1"]) + errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"value1"}, params["key1"])), errx) } if !reflect.DeepEqual(params["key2"], []string{"value2"}) { - errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value2"}, params["key2"]) + errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"value2"}, params["key2"])), errx) } _, _ = 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 = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"here"}, params["something"]) + errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"here"}, params["something"])), errx) } if !reflect.DeepEqual(params["key"], []string{"value"}) { - errx = errorutil.WrapfWithNil(errx, "expected %v, got %v", []string{"value"}, params["key"]) + errx = errkit.Append(errkit.New(fmt.Sprintf("expected %v, got %v", []string{"value"}, params["key"])), errx) } _, _ = 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 errorutil.NewWithErr(err).Msgf("failed to create temp file") + return errkit.Append(errkit.New("failed to create temp file"), err) } if _, err := FileLoc.Write([]byte("one\ntwo\n")); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to write payload to temp file") + return errkit.Append(errkit.New("failed to write payload to temp file"), err) } 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 errorutil.NewWithTag(filePath, "expected requests to be sent to `/one` and `/two` endpoints but were sent to `%v`", gotReqToEndpoints) + 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 nil } diff --git a/cmd/integration-test/loader.go b/cmd/integration-test/loader.go index d1114ef33..2967e9afb 100644 --- a/cmd/integration-test/loader.go +++ b/cmd/integration-test/loader.go @@ -10,7 +10,7 @@ import ( "github.com/julienschmidt/httprouter" "github.com/projectdiscovery/nuclei/v3/pkg/testutils" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithErr(err).Msgf("failed to load template with id") + return errkit.Append(errkit.New("failed to load template with id"), err) } return expectResultsCount(results, 1) } diff --git a/cmd/integration-test/profile-loader.go b/cmd/integration-test/profile-loader.go index 80ae4cfd4..19e57ba48 100644 --- a/cmd/integration-test/profile-loader.go +++ b/cmd/integration-test/profile-loader.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/projectdiscovery/nuclei/v3/pkg/testutils" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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 errorutil.NewWithErr(err).Msgf("failed to load template with id") + return errkit.Append(errkit.New("failed to load template with id"), err) } 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 errorutil.NewWithErr(err).Msgf("failed to load template with id") + return errkit.Append(errkit.New("failed to load template with id"), err) } 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 errorutil.NewWithErr(err).Msgf("failed to load template with id") + return errkit.Append(errkit.New("failed to load template with id"), err) } if len(results) < 1 { return fmt.Errorf("incorrect result: expected more results than %d, got %v", 1, len(results)) diff --git a/cmd/integration-test/template-dir.go b/cmd/integration-test/template-dir.go index 20691da04..96da87424 100644 --- a/cmd/integration-test/template-dir.go +++ b/cmd/integration-test/template-dir.go @@ -4,7 +4,7 @@ import ( "os" "github.com/projectdiscovery/nuclei/v3/pkg/testutils" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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 errorutil.NewWithErr(err).Msgf("failed to create temp dir") + return errkit.Append(errkit.New("failed to create temp dir"), err) } defer func() { _ = os.RemoveAll(tempdir) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index dd554a8a9..ba71a1e0f 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithErr(err).Msgf("couldn't create crash resume file") + return errkit.Append(errkit.New("couldn't create crash resume file"), err) } return nil }) diff --git a/cmd/tmc/main.go b/cmd/tmc/main.go index 8e4eb1ed2..69065436d 100644 --- a/cmd/tmc/main.go +++ b/cmd/tmc/main.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "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, errorutil.New("unexpected status code: %v", resp.Status) + return data, false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build() } 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, errorutil.NewWithTag("validate", templateResp.ValidateError[0].Message+": at line %v", templateResp.ValidateError[0].Mark.Line) + 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.New("validation failed").WithTag("validate") + return data, false, errkit.New("validate: validation failed").Build() } if templateResp.Error.Name != "" { - return data, false, errorutil.New("%s", templateResp.Error.Name) + return data, false, errkit.New(templateResp.Error.Name).Build() } if strings.TrimSpace(templateResp.Enhanced) == "" && !templateResp.Lint { if templateResp.LintError.Reason != "" { - return data, false, errorutil.NewWithTag("lint", templateResp.LintError.Reason+" : at line %v", templateResp.LintError.Mark.Line) + 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", "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.New("template enhance failed") + return data, false, errkit.New("template enhance failed").Build() } // 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, errorutil.New("unexpected status code: %v", resp.Status) + return data, false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build() } 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, errorutil.NewWithTag("validate", templateResp.ValidateError[0].Message+": at line %v", templateResp.ValidateError[0].Mark.Line) + 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.New("validation failed").WithTag("validate") + return data, false, errkit.New("validate: validation failed").Build() } if templateResp.Error.Name != "" { - return data, false, errorutil.New("%s", templateResp.Error.Name) + return data, false, errkit.New(templateResp.Error.Name).Build() } if strings.TrimSpace(templateResp.Updated) == "" && !templateResp.Lint { if templateResp.LintError.Reason != "" { - return data, false, errorutil.NewWithTag("lint", templateResp.LintError.Reason+" : at line %v", templateResp.LintError.Mark.Line) + 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", "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.New("template format failed") + return data, false, errkit.New("template format failed").Build() } // 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, errorutil.New("unexpected status code: %v", resp.Status) + return false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build() } 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, errorutil.NewWithTag("lint", lintResp.LintError.Reason+" : at line %v", lintResp.LintError.Mark.Line) + return false, errkit.New(fmt.Sprintf("lint: %s : at line %v", lintResp.LintError.Reason, lintResp.LintError.Mark.Line)).Build() } - return false, errorutil.NewWithTag("lint", "at line: %v", lintResp.LintError.Mark.Line) + return false, errkit.New(fmt.Sprintf("lint: at line: %v", lintResp.LintError.Mark.Line)).Build() } // 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, errorutil.New("unexpected status code: %v", resp.Status) + return false, errkit.New(fmt.Sprintf("unexpected status code: %v", resp.Status)).Build() } 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, errorutil.NewWithTag("validate", validateResp.ValidateError[0].Message+": at line %v", validateResp.ValidateError[0].Mark.Line) + return false, errkit.New(fmt.Sprintf("validate: %s: at line %v", validateResp.ValidateError[0].Message, validateResp.ValidateError[0].Mark.Line)).Build() } - return false, errorutil.New("validation failed").WithTag("validate") + return false, errkit.New("validate: validation failed").Build() } if validateResp.Error.Name != "" { - return false, errorutil.New("%s", validateResp.Error.Name) + return false, errkit.New(validateResp.Error.Name).Build() } - return false, errorutil.New("template validation failed") + return false, errkit.New("template validation failed").Build() } // parseAndAddMaxRequests parses and adds max requests to templates diff --git a/internal/pdcp/writer.go b/internal/pdcp/writer.go index 19e2c7e84..ed98d556e 100644 --- a/internal/pdcp/writer.go +++ b/internal/pdcp/writer.go @@ -19,7 +19,7 @@ import ( "github.com/projectdiscovery/retryablehttp-go" pdcpauth "github.com/projectdiscovery/utils/auth/pdcp" "github.com/projectdiscovery/utils/env" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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, errorutil.NewWithErr(err).Msgf("could not create output writer") + return nil, errkit.Append(errkit.New("could not create output writer"), err) } tmp, err := urlutil.Parse(creds.Server) if err != nil { - return nil, errorutil.NewWithErr(err).Msgf("could not parse server url") + return nil, errkit.Append(errkit.New("could not parse server url"), err) } 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 errorutil.NewWithErr(err).Msgf("could not upload chunk") + return errkit.Append(errkit.New("could not upload chunk"), err) } // 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 errorutil.NewWithErr(err).Msgf("could not create upload request") + return errkit.Append(errkit.New("could not create upload request"), err) } resp, err := u.client.Do(req) if err != nil { - return errorutil.NewWithErr(err).Msgf("could not upload results") + return errkit.Append(errkit.New("could not upload results"), err) } defer func() { _ = resp.Body.Close() }() bin, err := io.ReadAll(resp.Body) if err != nil { - return errorutil.NewWithErr(err).Msgf("could not get id from response") + return errkit.Append(errkit.New("could not get id from response"), err) } 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 errorutil.NewWithErr(err).Msgf("could not unmarshal response got %v", string(bin)) + return errkit.Append(errkit.New(fmt.Sprintf("could not unmarshal response got %v", string(bin))), err) } 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, errorutil.NewWithErr(err).Msgf("could not create cloud upload request") + return nil, errkit.Append(errkit.New("could not create cloud upload request"), err) } // add pdtm meta params req.Params.Merge(updateutils.GetpdtmParams(config.Version)) diff --git a/internal/runner/lazy.go b/internal/runner/lazy.go index 30664bfd5..27f223e6d 100644 --- a/internal/runner/lazy.go +++ b/internal/runner/lazy.go @@ -17,7 +17,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/scan" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/utils/env" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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, errorutil.NewWithErr(err).Msgf("failed to get template paths from secrets file") + return nil, errkit.Append(errkit.New("failed to get template paths from secrets file"), err) } 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, errorutil.NewWithErr(err).Msgf("failed to initialize dynamic auth templates store") + return nil, errkit.Append(errkit.New("failed to initialize dynamic auth templates store"), err) } return store, nil } diff --git a/internal/runner/proxy.go b/internal/runner/proxy.go index ec14302eb..4584eedcc 100644 --- a/internal/runner/proxy.go +++ b/internal/runner/proxy.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.WrapfWithNil(err, "failed to parse proxy got %v", err) + return errkit.Append(errkit.New(fmt.Sprintf("failed to parse proxy got %v", err)), err) } if options.ProxyInternal { _ = os.Setenv(HTTP_PROXY_ENV, proxyURL.String()) diff --git a/lib/config.go b/lib/config.go index 125442898..24af8fdbf 100644 --- a/lib/config.go +++ b/lib/config.go @@ -102,7 +102,7 @@ type InteractshOpts interactsh.Options func WithInteractshOptions(opts InteractshOpts) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported.Msgf("WithInteractshOptions") + return ErrOptionsNotSupported("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.Msgf("EnableStatsWithOpts") + return ErrOptionsNotSupported("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.Msgf("WithVerbosity") + return ErrOptionsNotSupported("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.Msgf("WithNetworkConfig") + return ErrOptionsNotSupported("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.Msgf("WithProxy") + return ErrOptionsNotSupported("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.Msgf("UseOutputWriter") + return ErrOptionsNotSupported("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.Msgf("UseStatsWriter") + return ErrOptionsNotSupported("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.Msgf("WithTemplateUpdateCallback") + return ErrOptionsNotSupported("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.Msgf("WithSandboxOptions") + return ErrOptionsNotSupported("WithSandboxOptions") } e.opts.AllowLocalFileAccess = allowLocalFileAccess e.opts.RestrictLocalNetworkAccess = restrictLocalNetworkAccess diff --git a/lib/multi.go b/lib/multi.go index 3c414116d..d224d09f6 100644 --- a/lib/multi.go +++ b/lib/multi.go @@ -13,7 +13,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/ratelimit" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "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 errorutil.New("Could not create workflow loader: %s\n", err) + return errkit.Append(errkit.New("Could not create workflow loader"), err) } unsafeOpts.executerOpts.WorkflowLoader = workflowLoader store, err := loader.New(loader.NewConfig(tmpEngine.opts, e.eng.catalog, unsafeOpts.executerOpts)) if err != nil { - return errorutil.New("Could not create loader client: %s\n", err) + return errkit.Append(errkit.New("Could not create loader client"), err) } store.Load() diff --git a/lib/sdk.go b/lib/sdk.go index d1d8314db..76fc8870b 100644 --- a/lib/sdk.go +++ b/lib/sdk.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "context" + "fmt" "io" "sync" @@ -28,7 +29,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/ratelimit" "github.com/projectdiscovery/retryablehttp-go" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "github.com/rs/xid" ) @@ -37,15 +38,18 @@ type NucleiSDKOptions func(e *NucleiEngine) error var ( // ErrNotImplemented is returned when a feature is not implemented - ErrNotImplemented = errorutil.New("Not implemented") + ErrNotImplemented = errkit.New("Not implemented").Build() // ErrNoTemplatesAvailable is returned when no templates are available to execute - ErrNoTemplatesAvailable = errorutil.New("No templates available") + ErrNoTemplatesAvailable = errkit.New("No templates available").Build() // ErrNoTargetsAvailable is returned when no targets are available to scan - 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") + ErrNoTargetsAvailable = errkit.New("No targets available").Build() ) +// 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 ( @@ -98,13 +102,13 @@ type NucleiEngine struct { func (e *NucleiEngine) LoadAllTemplates() error { workflowLoader, err := workflow.NewLoader(e.executerOpts) if err != nil { - return errorutil.New("Could not create workflow loader: %s\n", err) + return errkit.Append(errkit.New("Could not create workflow loader"), err) } e.executerOpts.WorkflowLoader = workflowLoader e.store, err = loader.New(loader.NewConfig(e.opts, e.catalog, e.executerOpts)) if err != nil { - return errorutil.New("Could not create loader client: %s\n", err) + return errkit.Append(errkit.New("Could not create loader client"), err) } e.store.Load() e.templatesLoaded = true diff --git a/pkg/authprovider/authx/dynamic.go b/pkg/authprovider/authx/dynamic.go index a3abc2204..9a2427555 100644 --- a/pkg/authprovider/authx/dynamic.go +++ b/pkg/authprovider/authx/dynamic.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.New("cannot unmarshal into nil Dynamic struct") + return errkit.New("cannot unmarshal into nil Dynamic struct").Build() } // 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 errorutil.New(" template-path is required for dynamic secret") + return errkit.New(" template-path is required for dynamic secret").Build() } if len(d.Variables) == 0 { - return errorutil.New("variables are required for dynamic secret") + return errkit.New("variables are required for dynamic secret").Build() } if d.Secret != nil { diff --git a/pkg/authprovider/authx/file.go b/pkg/authprovider/authx/file.go index e2f473727..fc749fda3 100644 --- a/pkg/authprovider/authx/file.go +++ b/pkg/authprovider/authx/file.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "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, errorutil.NewWithErr(err).Msgf("could not unmarshal yaml") + return nil, errkit.Append(errkit.New("could not unmarshal yaml"), err) } 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, errorutil.NewWithErr(err).Msgf("could not unmarshal json") + return nil, errkit.Append(errkit.New("could not unmarshal json"), err) } return &auth, nil } diff --git a/pkg/authprovider/file.go b/pkg/authprovider/file.go index 1c2ef51bf..02df46b6f 100644 --- a/pkg/authprovider/file.go +++ b/pkg/authprovider/file.go @@ -1,13 +1,14 @@ package authprovider import ( + "fmt" "net" "net/url" "regexp" "strings" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" urlutil "github.com/projectdiscovery/utils/url" ) @@ -30,16 +31,16 @@ func NewFileAuthProvider(path string, callback authx.LazyFetchSecret) (AuthProvi return nil, ErrNoSecrets } if len(store.Dynamic) > 0 && callback == nil { - return nil, errorutil.New("lazy fetch callback is required for dynamic secrets") + return nil, errkit.New("lazy fetch callback is required for dynamic secrets").Build() } for _, secret := range store.Secrets { if err := secret.Validate(); err != nil { - return nil, errorutil.NewWithErr(err).Msgf("invalid secret in file: %s", path) + return nil, errkit.Append(errkit.New(fmt.Sprintf("invalid secret in file: %s", path)), err) } } for i, dynamic := range store.Dynamic { if err := dynamic.Validate(); err != nil { - return nil, errorutil.NewWithErr(err).Msgf("invalid dynamic in file: %s", path) + return nil, errkit.Append(errkit.New(fmt.Sprintf("invalid dynamic in file: %s", path)), err) } dynamic.SetLazyFetchCallback(callback) store.Dynamic[i] = dynamic diff --git a/pkg/catalog/config/nucleiconfig.go b/pkg/catalog/config/nucleiconfig.go index 1f43d0c16..8496b69b3 100644 --- a/pkg/catalog/config/nucleiconfig.go +++ b/pkg/catalog/config/nucleiconfig.go @@ -13,7 +13,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" "github.com/projectdiscovery/utils/env" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithErr(err).Msgf("could not read nuclei ignore file") + return errkit.Append(errkit.New("could not read nuclei ignore file"), err) } c.NucleiIgnoreHash = fmt.Sprintf("%x", md5.Sum(bin)) // write config to disk return c.WriteTemplatesConfig() } - return errorutil.NewWithTag("config", "ignore file not found: could not update nuclei ignore hash") + return errkit.New("config: ignore file not found: could not update nuclei ignore hash").Build() } // 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 errorutil.NewWithErr(err).Msgf("could not write nuclei config file at %s", c.getTemplatesConfigFilePath()) + return errkit.Append(errkit.New(fmt.Sprintf("could not write nuclei config file at %s", c.getTemplatesConfigFilePath())), err) } 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 errorutil.NewWithTag("config", "nuclei config file at %s does not exist", c.getTemplatesConfigFilePath()) + return errkit.New(fmt.Sprintf("config: nuclei config file at %s does not exist", c.getTemplatesConfigFilePath())).Build() } var cfg *Config bin, err := os.ReadFile(c.getTemplatesConfigFilePath()) if err != nil { - return errorutil.NewWithErr(err).Msgf("could not read nuclei config file at %s", c.getTemplatesConfigFilePath()) + return errkit.Append(errkit.New(fmt.Sprintf("could not read nuclei config file at %s", c.getTemplatesConfigFilePath())), err) } if err := json.Unmarshal(bin, &cfg); err != nil { - return errorutil.NewWithErr(err).Msgf("could not unmarshal nuclei config file at %s", c.getTemplatesConfigFilePath()) + return errkit.Append(errkit.New(fmt.Sprintf("could not unmarshal nuclei config file at %s", c.getTemplatesConfigFilePath())), err) } // apply config c.TemplatesDirectory = cfg.TemplatesDirectory @@ -292,10 +292,10 @@ func (c *Config) WriteTemplatesConfig() error { } bin, err := json.Marshal(c) if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to marshal nuclei config") + return errkit.Append(errkit.New("failed to marshal nuclei config"), err) } if err = os.WriteFile(c.getTemplatesConfigFilePath(), bin, 0600); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to write nuclei config file at %s", c.getTemplatesConfigFilePath()) + return errkit.Append(errkit.New(fmt.Sprintf("failed to write nuclei config file at %s", c.getTemplatesConfigFilePath())), err) } 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 errorutil.NewWithErr(err).Msgf("could not create nuclei config directory at %s", c.configDir) + return errkit.Append(errkit.New(fmt.Sprintf("could not create nuclei config directory at %s", c.configDir)), err) } } return nil diff --git a/pkg/catalog/loader/ai_loader.go b/pkg/catalog/loader/ai_loader.go index 998d2b0b9..5b30c4973 100644 --- a/pkg/catalog/loader/ai_loader.go +++ b/pkg/catalog/loader/ai_loader.go @@ -3,6 +3,7 @@ package loader import ( "bytes" "encoding/json" + "fmt" "io" "net/http" "os" @@ -14,7 +15,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types" "github.com/projectdiscovery/retryablehttp-go" pdcpauth "github.com/projectdiscovery/utils/auth/pdcp" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) const ( @@ -33,27 +34,27 @@ type AITemplateResponse struct { func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, error) { prompt = strings.TrimSpace(prompt) if len(prompt) < 5 { - return nil, errorutil.New("Prompt is too short. Please provide a more descriptive prompt") + return nil, errkit.New("Prompt is too short. Please provide a more descriptive prompt").Build() } if len(prompt) > 3000 { - return nil, errorutil.New("Prompt is too long. Please limit to 3000 characters") + return nil, errkit.New("Prompt is too long. Please limit to 3000 characters").Build() } template, templateID, err := generateAITemplate(prompt) if err != nil { - return nil, errorutil.New("Failed to generate template: %v", err) + return nil, errkit.New(fmt.Sprintf("Failed to generate template: %v", err)).Build() } pdcpTemplateDir := filepath.Join(config.DefaultConfig.GetTemplateDir(), "pdcp") if err := os.MkdirAll(pdcpTemplateDir, 0755); err != nil { - return nil, errorutil.New("Failed to create pdcp template directory: %v", err) + return nil, errkit.New(fmt.Sprintf("Failed to create pdcp template directory: %v", err)).Build() } templateFile := filepath.Join(pdcpTemplateDir, templateID+".yaml") err = os.WriteFile(templateFile, []byte(template), 0644) if err != nil { - return nil, errorutil.New("Failed to generate template: %v", err) + return nil, errkit.New(fmt.Sprintf("Failed to generate template: %v", err)).Build() } options.Logger.Info().Msgf("Generated template available at: https://cloud.projectdiscovery.io/templates/%s", templateID) @@ -91,22 +92,22 @@ func generateAITemplate(prompt string) (string, string, error) { } jsonBody, err := json.Marshal(reqBody) if err != nil { - return "", "", errorutil.New("Failed to marshal request body: %v", err) + return "", "", errkit.New(fmt.Sprintf("Failed to marshal request body: %v", err)).Build() } req, err := http.NewRequest(http.MethodPost, aiTemplateGeneratorAPIEndpoint, bytes.NewBuffer(jsonBody)) if err != nil { - return "", "", errorutil.New("Failed to create HTTP request: %v", err) + return "", "", errkit.New(fmt.Sprintf("Failed to create HTTP request: %v", err)).Build() } ph := pdcpauth.PDCPCredHandler{} creds, err := ph.GetCreds() if err != nil { - return "", "", errorutil.New("Failed to get PDCP credentials: %v", err) + return "", "", errkit.New(fmt.Sprintf("Failed to get PDCP credentials: %v", err)).Build() } if creds == nil { - return "", "", errorutil.New("PDCP API Key not configured, Create one for free at https://cloud.projectdiscovery.io/") + return "", "", errkit.New("PDCP API Key not configured, Create one for free at https://cloud.projectdiscovery.io/").Build() } req.Header.Set("Content-Type", "application/json") @@ -114,28 +115,28 @@ func generateAITemplate(prompt string) (string, string, error) { resp, err := retryablehttp.DefaultClient().Do(req) if err != nil { - return "", "", errorutil.New("Failed to send HTTP request: %v", err) + return "", "", errkit.New(fmt.Sprintf("Failed to send HTTP request: %v", err)).Build() } defer func() { _ = resp.Body.Close() }() if resp.StatusCode == http.StatusUnauthorized { - return "", "", errorutil.New("Invalid API Key or API Key not configured, Create one for free at https://cloud.projectdiscovery.io/") + return "", "", errkit.New("Invalid API Key or API Key not configured, Create one for free at https://cloud.projectdiscovery.io/").Build() } if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) - return "", "", errorutil.New("API returned status code %d: %s", resp.StatusCode, string(body)) + return "", "", errkit.New(fmt.Sprintf("API returned status code %d: %s", resp.StatusCode, string(body))).Build() } var result AITemplateResponse if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - return "", "", errorutil.New("Failed to decode API response: %v", err) + return "", "", errkit.New(fmt.Sprintf("Failed to decode API response: %v", err)).Build() } if result.TemplateID == "" || result.Completion == "" { - return "", "", errorutil.New("Failed to generate template") + return "", "", errkit.New("Failed to generate template").Build() } return result.Completion, result.TemplateID, nil diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 2c3403240..069e99b50 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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, errorutil.NewWithErr(err).Msgf("Could not load template %s: got %v", uri, remoteTemplates) + return nil, errkit.Append(errkit.New(fmt.Sprintf("Could not load template %s: got %v", uri, remoteTemplates)), err) } resp, err := retryablehttp.Get(remoteTemplates[0]) if err != nil { diff --git a/pkg/external/customtemplates/azure_blob.go b/pkg/external/customtemplates/azure_blob.go index 2610e2de9..180c45d8e 100644 --- a/pkg/external/customtemplates/azure_blob.go +++ b/pkg/external/customtemplates/azure_blob.go @@ -3,6 +3,7 @@ package customtemplates import ( "bytes" "context" + "fmt" "os" "path/filepath" "strings" @@ -12,7 +13,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) var _ Provider = &customTemplateAzureBlob{} @@ -29,7 +30,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, errorutil.NewWithErr(err).Msgf("Error establishing Azure Blob client for %s", options.AzureContainerName) + return nil, errkit.Append(errkit.New(fmt.Sprintf("Error establishing Azure Blob client for %s", options.AzureContainerName)), err) } // Create a new Azure Blob Storage container object diff --git a/pkg/external/customtemplates/gitlab.go b/pkg/external/customtemplates/gitlab.go index 169928bef..fce4caa2d 100644 --- a/pkg/external/customtemplates/gitlab.go +++ b/pkg/external/customtemplates/gitlab.go @@ -3,13 +3,14 @@ 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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" gitlab "gitlab.com/gitlab-org/api/client-go" ) @@ -28,7 +29,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, errorutil.NewWithErr(err).Msgf("Error establishing GitLab client for %s %s", options.GitLabServerURL, err) + return nil, errkit.Append(errkit.New(fmt.Sprintf("Error establishing GitLab client for %s %s", options.GitLabServerURL, err)), err) } // Create a new GitLab service client diff --git a/pkg/external/customtemplates/s3.go b/pkg/external/customtemplates/s3.go index 29bb465fd..8b4eabff9 100644 --- a/pkg/external/customtemplates/s3.go +++ b/pkg/external/customtemplates/s3.go @@ -2,6 +2,7 @@ package customtemplates import ( "context" + "fmt" "os" "path/filepath" "strings" @@ -14,7 +15,7 @@ import ( "github.com/projectdiscovery/gologger" nucleiConfig "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -64,7 +65,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, errorutil.NewWithErr(err).Msgf("error downloading s3 bucket %s", options.AwsBucketName) + return nil, errkit.Append(errkit.New(fmt.Sprintf("error downloading s3 bucket %s", options.AwsBucketName)), err) } ctBucket := &customTemplateS3Bucket{ bucketName: options.AwsBucketName, diff --git a/pkg/external/customtemplates/templates_provider.go b/pkg/external/customtemplates/templates_provider.go index 471d16482..a4691d5bf 100644 --- a/pkg/external/customtemplates/templates_provider.go +++ b/pkg/external/customtemplates/templates_provider.go @@ -4,7 +4,7 @@ import ( "context" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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, errorutil.NewWithErr(err).Msgf("could not create github providers for custom templates") + return nil, errkit.Append(errkit.New("could not create github providers for custom templates"), err) } 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, errorutil.NewWithErr(err).Msgf("could not create s3 providers for custom templates") + return nil, errkit.Append(errkit.New("could not create s3 providers for custom templates"), err) } 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, errorutil.NewWithErr(err).Msgf("could not create azure providers for custom templates") + return nil, errkit.Append(errkit.New("could not create azure providers for custom templates"), err) } 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, errorutil.NewWithErr(err).Msgf("could not create gitlab providers for custom templates") + return nil, errkit.Append(errkit.New("could not create gitlab providers for custom templates"), err) } for _, v := range gitlabProviders { ctm.providers = append(ctm.providers, v) diff --git a/pkg/fuzz/execute.go b/pkg/fuzz/execute.go index eda78f4d0..ddec76505 100644 --- a/pkg/fuzz/execute.go +++ b/pkg/fuzz/execute.go @@ -17,15 +17,16 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/marker" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" "github.com/projectdiscovery/retryablehttp-go" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" mapsutil "github.com/projectdiscovery/utils/maps" sliceutil "github.com/projectdiscovery/utils/slice" urlutil "github.com/projectdiscovery/utils/url" ) -var ( - ErrRuleNotApplicable = errorutil.NewWithFmt("rule not applicable: %v") -) +// ErrRuleNotApplicable returns a rule not applicable error +func ErrRuleNotApplicable(reason interface{}) error { + return errkit.New(fmt.Sprintf("rule not applicable: %v", reason)).Build() +} // IsErrRuleNotApplicable checks if an error is due to rule not applicable func IsErrRuleNotApplicable(err error) bool { @@ -89,10 +90,10 @@ type GeneratedRequest struct { // goroutines. func (rule *Rule) Execute(input *ExecuteRuleInput) (err error) { if !rule.isInputURLValid(input.Input) { - return ErrRuleNotApplicable.Msgf("invalid input url: %v", input.Input.MetaInput.Input) + return ErrRuleNotApplicable(fmt.Sprintf("invalid input url: %v", input.Input.MetaInput.Input)) } if input.BaseRequest == nil && input.Input.MetaInput.ReqResp == nil { - return ErrRuleNotApplicable.Msgf("both base request and reqresp are nil for %v", input.Input.MetaInput.Input) + return ErrRuleNotApplicable(fmt.Sprintf("both base request and reqresp are nil for %v", input.Input.MetaInput.Input)) } var finalComponentList []component.Component @@ -144,7 +145,7 @@ func (rule *Rule) Execute(input *ExecuteRuleInput) (err error) { } if len(finalComponentList) == 0 { - return ErrRuleNotApplicable.Msgf("no component matched on this rule") + return ErrRuleNotApplicable("no component matched on this rule") } baseValues := input.Values diff --git a/pkg/input/formats/openapi/generator.go b/pkg/input/formats/openapi/generator.go index 30778d8dc..3d758cbc9 100644 --- a/pkg/input/formats/openapi/generator.go +++ b/pkg/input/formats/openapi/generator.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "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, errorutil.NewWithTag("openapi", "security requirements (%+v) without any security schemes found in openapi file", schema.Security) + return nil, errkit.New(fmt.Sprintf("openapi: security requirements (%+v) without any security schemes found in openapi file", schema.Security)).Build() } 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, errorutil.NewWithTag("openapi", "security requirement (%+v) not found in openapi file", security) + return nil, errkit.New(fmt.Sprintf("openapi: security requirement (%+v) not found in openapi file", security)).Build() } } if !found { - return nil, errorutil.NewWithTag("openapi", "security requirement (%+v) not found in openapi file", requirement) + return nil, errkit.New(fmt.Sprintf("openapi: security requirement (%+v) not found in openapi file", requirement)).Build() } 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, errorutil.NewWithTag("openapi", "unsupported security scheme type (%s) found in openapi file", scheme.Value.Type) + return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme type (%s) found in openapi file", scheme.Value.Type)).Build() } if scheme.Value.Type == "http" { // check scheme if !generic.EqualsAny(scheme.Value.Scheme, "basic", "bearer") { - return nil, errorutil.NewWithTag("openapi", "unsupported security scheme (%s) found in openapi file", scheme.Value.Scheme) + return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme (%s) found in openapi file", scheme.Value.Scheme)).Build() } // 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, errorutil.NewWithTag("openapi", "security scheme (%s) name is empty", scheme.Value.Type) + return nil, errkit.New(fmt.Sprintf("openapi: security scheme (%s) name is empty", scheme.Value.Type)).Build() } if !generic.EqualsAny(scheme.Value.In, "query", "header", "cookie") { - return nil, errorutil.NewWithTag("openapi", "unsupported security scheme (%s) in (%s) found in openapi file", scheme.Value.Type, scheme.Value.In) + return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme (%s) in (%s) found in openapi file", scheme.Value.Type, scheme.Value.In)).Build() } // create parameters using the scheme switch scheme.Value.In { @@ -482,5 +482,5 @@ func GenerateParameterFromSecurityScheme(scheme *openapi3.SecuritySchemeRef) (*o return c, nil } } - return nil, errorutil.NewWithTag("openapi", "unsupported security scheme type (%s) found in openapi file", scheme.Value.Type) + return nil, errkit.New(fmt.Sprintf("openapi: unsupported security scheme type (%s) found in openapi file", scheme.Value.Type)).Build() } diff --git a/pkg/input/provider/interface.go b/pkg/input/provider/interface.go index 1ac068514..c93a329de 100644 --- a/pkg/input/provider/interface.go +++ b/pkg/input/provider/interface.go @@ -13,15 +13,19 @@ 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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" stringsutil "github.com/projectdiscovery/utils/strings" ) var ( - ErrNotImplemented = errorutil.NewWithFmt("provider %s does not implement %s") - ErrInactiveInput = fmt.Errorf("input is inactive") + 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" diff --git a/pkg/installer/template.go b/pkg/installer/template.go index d9f3d5ae1..62fefb0a6 100644 --- a/pkg/installer/template.go +++ b/pkg/installer/template.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithErr(err).Msgf("failed to install templates at %s", config.DefaultConfig.TemplatesDirectory) + return errkit.Append(errkit.New(fmt.Sprintf("failed to install templates at %s", config.DefaultConfig.TemplatesDirectory)), err) } if t.CustomTemplates != nil { t.CustomTemplates.Download(context.TODO()) @@ -121,7 +121,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 errorutil.NewWithErr(err).Msgf("failed to create directory at %s", dir) + return errkit.Append(errkit.New(fmt.Sprintf("failed to create directory at %s", dir)), err) } } if t.DisablePublicTemplates { @@ -130,12 +130,12 @@ func (t *TemplateManager) installTemplatesAt(dir string) error { } ghrd, err := updateutils.NewghReleaseDownloader(config.OfficialNucleiTemplatesRepoName) if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir) + return errkit.Append(errkit.New(fmt.Sprintf("failed to install templates at %s", dir)), err) } // write templates to disk if err := t.writeTemplatesToDisk(ghrd, dir); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to write templates to disk at %s", dir) + return errkit.Append(errkit.New(fmt.Sprintf("failed to write templates to disk at %s", dir)), err) } gologger.Info().Msgf("Successfully installed nuclei-templates at %s", dir) return nil @@ -156,7 +156,7 @@ func (t *TemplateManager) updateTemplatesAt(dir string) error { ghrd, err := updateutils.NewghReleaseDownloader(config.OfficialNucleiTemplatesRepoName) if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to install templates at %s", dir) + return errkit.Append(errkit.New(fmt.Sprintf("failed to install templates at %s", dir)), err) } latestVersion := ghrd.Latest.GetTagName() @@ -177,7 +177,7 @@ func (t *TemplateManager) updateTemplatesAt(dir string) error { newchecksums, err := t.getChecksumFromDir(dir) if err != nil { // unlikely this case will happen - return errorutil.NewWithErr(err).Msgf("failed to get checksums from %s after update", dir) + return errkit.Append(errkit.New(fmt.Sprintf("failed to get checksums from %s after update", dir)), err) } // summarize all changes @@ -299,7 +299,7 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo bin, err := io.ReadAll(r) if err != nil { // if error occurs, iteration also stops - return errorutil.NewWithErr(err).Msgf("failed to read file %s", uri) + return errkit.Append(errkit.New(fmt.Sprintf("failed to read file %s", uri)), err) } // TODO: It might be better to just download index file from nuclei templates repo // instead of creating it from scratch @@ -310,7 +310,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 errorutil.NewWithErr(err).Msgf("failed to write file %s", uri) + return errkit.Append(errkit.New(fmt.Sprintf("failed to write file %s", uri)), err) } // after successful write, remove old template if err := os.Remove(oldPath); err != nil { @@ -325,20 +325,20 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo } err = ghrd.DownloadSourceWithCallback(!HideProgressBar, callbackFunc) if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to download templates") + return errkit.Append(errkit.New("failed to download templates"), err) } if err := config.DefaultConfig.WriteTemplatesConfig(); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to write templates config") + return errkit.Append(errkit.New("failed to write templates config"), err) } // update ignore hash after writing new templates if err := config.DefaultConfig.UpdateNucleiIgnoreHash(); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to update nuclei ignore hash") + return errkit.Append(errkit.New("failed to update nuclei ignore hash"), err) } // update templates version in config file if err := config.DefaultConfig.SetTemplatesVersion(ghrd.Latest.GetTagName()); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to update templates version") + return errkit.Append(errkit.New("failed to update templates version"), err) } PurgeEmptyDirectories(dir) @@ -348,11 +348,11 @@ func (t *TemplateManager) writeTemplatesToDisk(ghrd *updateutils.GHReleaseDownlo index, err := config.GetNucleiTemplatesIndex() if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to get nuclei templates index") + return errkit.Append(errkit.New("failed to get nuclei templates index"), err) } if err = config.DefaultConfig.WriteTemplatesIndex(index); err != nil { - return errorutil.NewWithErr(err).Msgf("failed to write nuclei templates index") + return errkit.Append(errkit.New("failed to write nuclei templates index"), err) } if !HideReleaseNotes { @@ -448,5 +448,8 @@ func (t *TemplateManager) calculateChecksumMap(dir string) (map[string]string, e } return nil }) - return checksumMap, errorutil.WrapfWithNil(err, "failed to calculate checksums of templates") + if err != nil { + return nil, errkit.Append(errkit.New("failed to calculate checksums of templates"), err) + } + return checksumMap, nil } diff --git a/pkg/installer/util.go b/pkg/installer/util.go index af7482621..a0bc99751 100644 --- a/pkg/installer/util.go +++ b/pkg/installer/util.go @@ -14,7 +14,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) // 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, errorutil.New("version not found") + return nil, errkit.New("version not found").Build() } data, err := io.ReadAll(resp.Body) if err != nil { diff --git a/pkg/js/devtools/tsgen/scrape.go b/pkg/js/devtools/tsgen/scrape.go index 960700f57..3c846ad7d 100644 --- a/pkg/js/devtools/tsgen/scrape.go +++ b/pkg/js/devtools/tsgen/scrape.go @@ -6,7 +6,7 @@ import ( "regexp" "strings" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) // 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 errorutil.New("package %v for type %v not found", pkgName, typeName) + return errkit.New(fmt.Sprintf("package %v for type %v not found", pkgName, typeName)).Build() } // get type obj := pkg.Types.Scope().Lookup(baseTypeName) if obj == nil { - return errorutil.New("type %v not found in package %+v", typeName, pkg) + return errkit.New(fmt.Sprintf("type %v not found in package %+v", typeName, pkg)).Build() } // Ensure the object is a type name typeNameObj, ok := obj.(*types.TypeName) if !ok { - return errorutil.New("%v is not a type name", typeName) + return errkit.New(fmt.Sprintf("%v is not a type name", typeName)).Build() } // Ensure the type is a named struct type namedStruct, ok := typeNameObj.Type().Underlying().(*types.Struct) diff --git a/pkg/js/global/scripts.go b/pkg/js/global/scripts.go index 6101eaf42..5bd625cbc 100644 --- a/pkg/js/global/scripts.go +++ b/pkg/js/global/scripts.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "embed" + "fmt" "math/rand" "net" "reflect" @@ -17,7 +18,6 @@ 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 errorutil.NewWithErr(err).Msgf("could not import default modules %v", defaultImports) + return errkit.Append(errkit.New(fmt.Sprintf("could not import default modules %v", defaultImports)), err) } return nil diff --git a/pkg/js/gojs/set.go b/pkg/js/gojs/set.go index 6aff9f1c7..72aece402 100644 --- a/pkg/js/gojs/set.go +++ b/pkg/js/gojs/set.go @@ -2,15 +2,16 @@ package gojs import ( "context" + "fmt" "reflect" "github.com/Mzack9999/goja" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) var ( - ErrInvalidFuncOpts = errorutil.NewWithFmt("invalid function options: %v") - ErrNilRuntime = errorutil.New("runtime is nil") + ErrInvalidFuncOpts = errkit.New("invalid function options: %v").Build() + ErrNilRuntime = errkit.New("runtime is nil").Build() ) type FuncOpts struct { @@ -83,7 +84,7 @@ func RegisterFuncWithSignature(runtime *goja.Runtime, opts FuncOpts) error { return ErrNilRuntime } if !opts.valid() { - return ErrInvalidFuncOpts.Msgf("name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description) + return errkit.New(fmt.Sprintf("invalid function options: name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description)).Build() } // Wrap the function with context injection diff --git a/pkg/js/libs/mssql/mssql.go b/pkg/js/libs/mssql/mssql.go index 4f9caf275..f1a538db2 100644 --- a/pkg/js/libs/mssql/mssql.go +++ b/pkg/js/libs/mssql/mssql.go @@ -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.Msgf(host) + return false, protocolstate.ErrHostDenied(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.Msgf(host) + return false, protocolstate.ErrHostDenied(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.Msgf(host) + return nil, protocolstate.ErrHostDenied(host) } target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) diff --git a/pkg/js/libs/mysql/mysql.go b/pkg/js/libs/mysql/mysql.go index c48c73a83..a059766d3 100644 --- a/pkg/js/libs/mysql/mysql.go +++ b/pkg/js/libs/mysql/mysql.go @@ -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.Msgf(host) + return false, protocolstate.ErrHostDenied(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.Msgf(host) + return false, protocolstate.ErrHostDenied(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.Msgf(host) + return info, protocolstate.ErrHostDenied(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.Msgf(opts.Host) + return nil, protocolstate.ErrHostDenied(opts.Host) } // executing queries implies the remote mysql service diff --git a/pkg/js/libs/net/net.go b/pkg/js/libs/net/net.go index 1db091636..2f486bfa5 100644 --- a/pkg/js/libs/net/net.go +++ b/pkg/js/libs/net/net.go @@ -10,7 +10,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "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{}, errorutil.NewWithErr(err).Msgf("failed to read %d bytes", N) + return []byte{}, errkit.Append(errkit.New(fmt.Sprintf("failed to read %d bytes", N)), err) } 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{}, errorutil.NewWithErr(err).Msgf("failed to read %d bytes", N) + return []byte{}, errkit.Append(errkit.New(fmt.Sprintf("failed to read %d bytes", N)), err) } return b[:n], nil } diff --git a/pkg/js/libs/postgres/postgres.go b/pkg/js/libs/postgres/postgres.go index 322048a8b..4dd1cd542 100644 --- a/pkg/js/libs/postgres/postgres.go +++ b/pkg/js/libs/postgres/postgres.go @@ -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.Msgf(host) + return nil, protocolstate.ErrHostDenied(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.Msgf(host) + return false, protocolstate.ErrHostDenied(host) } target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) diff --git a/pkg/js/libs/redis/redis.go b/pkg/js/libs/redis/redis.go index 84b96d86b..501788243 100644 --- a/pkg/js/libs/redis/redis.go +++ b/pkg/js/libs/redis/redis.go @@ -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.Msgf(host) + return "", protocolstate.ErrHostDenied(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.Msgf(host) + return false, protocolstate.ErrHostDenied(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.Msgf(host) + return "", protocolstate.ErrHostDenied(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.Msgf(host) + return false, protocolstate.ErrHostDenied(host) } // create a new client client := redis.NewClient(&redis.Options{ diff --git a/pkg/js/libs/smb/smb.go b/pkg/js/libs/smb/smb.go index 7dc2dc83b..62a804609 100644 --- a/pkg/js/libs/smb/smb.go +++ b/pkg/js/libs/smb/smb.go @@ -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.Msgf(host) + return nil, protocolstate.ErrHostDenied(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.Msgf(host) + return nil, protocolstate.ErrHostDenied(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.Msgf(host) + return nil, protocolstate.ErrHostDenied(host) } dialer := protocolstate.GetDialersWithId(executionId) if dialer == nil { diff --git a/pkg/js/libs/smb/smbghost.go b/pkg/js/libs/smb/smbghost.go index 69ddcca1e..bf498f3ba 100644 --- a/pkg/js/libs/smb/smbghost.go +++ b/pkg/js/libs/smb/smbghost.go @@ -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.Msgf(host) + return false, protocolstate.ErrHostDenied(host) } addr := net.JoinHostPort(host, strconv.Itoa(port)) dialer := protocolstate.GetDialersWithId(executionId) diff --git a/pkg/js/libs/smtp/smtp.go b/pkg/js/libs/smtp/smtp.go index d4a7e0227..f0f4b90b1 100644 --- a/pkg/js/libs/smtp/smtp.go +++ b/pkg/js/libs/smtp/smtp.go @@ -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.Msgf(host+":"+port).Error()) + c.nj.Require(protocolstate.IsHostAllowed(executionId, host+":"+port), protocolstate.ErrHostDenied(host+":"+port).Error()) // Link Constructor to Client and return return utils.LinkConstructor(call, runtime, c) diff --git a/pkg/js/libs/ssh/ssh.go b/pkg/js/libs/ssh/ssh.go index 17b35afe5..ebb041e20 100644 --- a/pkg/js/libs/ssh/ssh.go +++ b/pkg/js/libs/ssh/ssh.go @@ -7,7 +7,7 @@ import ( "time" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" "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 "", errorutil.New("no connection") + return "", errkit.New("no connection").Build() } session, err := c.connection.NewSession() if err != nil { @@ -177,14 +177,14 @@ type connectOptions struct { func (c *connectOptions) validate() error { if c.Host == "" { - return errorutil.New("host is required") + return errkit.New("host is required").Build() } if c.Port <= 0 { - return errorutil.New("port is required") + return errkit.New("port is required").Build() } if !protocolstate.IsHostAllowed(c.ExecutionId, c.Host) { // host is not valid according to network policy - return protocolstate.ErrHostDenied.Msgf(c.Host) + return protocolstate.ErrHostDenied(c.Host) } if c.Timeout == 0 { c.Timeout = 10 * time.Second diff --git a/pkg/operators/common/dsl/dsl.go b/pkg/operators/common/dsl/dsl.go index 56ac06509..a424790d5 100644 --- a/pkg/operators/common/dsl/dsl.go +++ b/pkg/operators/common/dsl/dsl.go @@ -61,11 +61,12 @@ func init() { return nil, fmt.Errorf("invalid dns type") } - err := dnsclientpool.Init(&types.Options{}) + options := &types.Options{} + err := dnsclientpool.Init(options) if err != nil { return nil, err } - dnsClient, err := dnsclientpool.Get(nil, &dnsclientpool.Configuration{}) + dnsClient, err := dnsclientpool.Get(options, &dnsclientpool.Configuration{}) if err != nil { return nil, err } diff --git a/pkg/operators/common/dsl/dsl_test.go b/pkg/operators/common/dsl/dsl_test.go index f83fb2073..40564ca18 100644 --- a/pkg/operators/common/dsl/dsl_test.go +++ b/pkg/operators/common/dsl/dsl_test.go @@ -5,10 +5,15 @@ 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", @@ -17,7 +22,7 @@ func TestDslExpressions(t *testing.T) { `resolve("scanme.sh","soa")`: "ns69.domaincontrol.com", } - testDslExpressionScenarios(t, dslExpressions) + testDslExpressionScenariosWithDNS(t, dslExpressions, googleDNS) } func evaluateExpression(t *testing.T, dslExpression string) interface{} { @@ -34,7 +39,13 @@ func evaluateExpression(t *testing.T, dslExpression string) interface{} { return actualResult } -func testDslExpressionScenarios(t *testing.T, dslExpressions map[string]interface{}) { +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") + for dslExpression, expectedResult := range dslExpressions { t.Run(dslExpression, func(t *testing.T) { actualResult := evaluateExpression(t, dslExpression) diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index 4af590c77..0a17c9f3f 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -33,7 +33,6 @@ 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 ( @@ -114,7 +113,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { if options.Options.Validate { options.Logger.Error().Msgf("%s <- %s", errMsg, err) } else { - return errorutil.NewWithErr(err).Msgf(errMsg) + return errkit.Append(errkit.New(errMsg), err) } } else { request.gozero = engine @@ -154,7 +153,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { if request.PreCondition != "" { preConditionCompiled, err := compiler.SourceAutoMode(request.PreCondition, false) if err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not compile pre-condition: %s", err) + return errkit.New(fmt.Sprintf("%s: could not compile pre-condition: %s", request.TemplateID, err)).Build() } request.preConditionCompiled = preConditionCompiled } @@ -231,7 +230,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa Context: input.Context(), }) if err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err) + return errkit.New(fmt.Sprintf("%s: could not execute pre-condition: %s", request.TemplateID, err)).Build() } if !result.GetSuccess() || types.ToString(result["error"]) != "" { gologger.Warning().Msgf("[%s] Precondition for request %s was not satisfied\n", request.TemplateID, request.PreCondition) diff --git a/pkg/protocols/common/interactsh/interactsh.go b/pkg/protocols/common/interactsh/interactsh.go index 6bb70709f..6cf7b1228 100644 --- a/pkg/protocols/common/interactsh/interactsh.go +++ b/pkg/protocols/common/interactsh/interactsh.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -88,7 +88,7 @@ func (c *Client) poll() error { KeepAliveInterval: time.Minute, }) if err != nil { - return errorutil.NewWithErr(err).Msgf("could not create client") + return errkit.Append(errkit.New("could not create client"), err) } 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 errorutil.IsAny(err, gcache.KeyNotFoundError) || items == nil { + if errors.Is(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 errorutil.NewWithErr(err).Msgf("could not perform interactsh polling") + return errkit.Append(errkit.New("could not perform interactsh polling"), err) } return nil } @@ -239,7 +239,7 @@ func (c *Client) URL() (string, error) { err = c.poll() }) if err != nil { - return "", errorutil.NewWithErr(err).Wrap(ErrInteractshClientNotInitialized) + return "", errkit.Append(ErrInteractshClientNotInitialized, err) } if c.interactsh == nil { diff --git a/pkg/protocols/common/protocolstate/file.go b/pkg/protocols/common/protocolstate/file.go index 180d5a0b5..0ca4dd3b7 100644 --- a/pkg/protocols/common/protocolstate/file.go +++ b/pkg/protocols/common/protocolstate/file.go @@ -1,11 +1,12 @@ package protocolstate import ( + "fmt" "strings" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" fileutil "github.com/projectdiscovery/utils/file" mapsutil "github.com/projectdiscovery/utils/maps" ) @@ -67,12 +68,12 @@ func NormalizePath(options *types.Options, filePath string) (string, error) { } cleaned, err := fileutil.ResolveNClean(filePath, config.DefaultConfig.GetTemplateDir()) if err != nil { - return "", errorutil.NewWithErr(err).Msgf("could not resolve and clean path %v", filePath) + return "", errkit.Append(errkit.New(fmt.Sprintf("could not resolve and clean path %v", filePath)), err) } // 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 "", errorutil.New("path %v is outside nuclei-template directory and -lfa is not enabled", filePath) + return "", errkit.New(fmt.Sprintf("path %v is outside nuclei-template directory and -lfa is not enabled", filePath)).Build() } diff --git a/pkg/protocols/common/protocolstate/headless.go b/pkg/protocols/common/protocolstate/headless.go index 1d9970119..ee75c3b31 100644 --- a/pkg/protocols/common/protocolstate/headless.go +++ b/pkg/protocols/common/protocolstate/headless.go @@ -2,6 +2,7 @@ package protocolstate import ( "context" + "fmt" "net" "strings" @@ -9,7 +10,7 @@ import ( "github.com/go-rod/rod/lib/proto" "github.com/projectdiscovery/networkpolicy" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" stringsutil "github.com/projectdiscovery/utils/strings" urlutil "github.com/projectdiscovery/utils/url" "go.uber.org/multierr" @@ -17,10 +18,15 @@ import ( // initialize state of headless protocol -var ( - ErrURLDenied = errorutil.NewWithFmt("headless: url %v dropped by rule: %v") - ErrHostDenied = errorutil.NewWithFmt("host %v dropped by network policy") -) +// 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() +} func GetNetworkPolicy(ctx context.Context) *networkpolicy.NetworkPolicy { execCtx := GetExecutionContext(ctx) @@ -41,15 +47,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.Msgf(reqURL, "use of file:// protocol disabled use '-lfa' to enable")) + return multierr.Combine(FailWithReason(page, e), ErrURLDenied(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.Msgf(reqURL, "protocol blocked by network policy")) + return multierr.Combine(FailWithReason(page, e), ErrURLDenied(reqURL, "protocol blocked by network policy")) } if !isValidHost(options, reqURL) { - return multierr.Combine(FailWithReason(page, e), ErrURLDenied.Msgf(reqURL, "address blocked by network policy")) + return multierr.Combine(FailWithReason(page, e), ErrURLDenied(reqURL, "address blocked by network policy")) } return nil } diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index 244d740c8..86f95a0e8 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" urlutil "github.com/projectdiscovery/utils/url" ) @@ -78,7 +78,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, errorutil.NewWithErr(err).Msgf("could not parse URL %s", target) + return nil, nil, errkit.Append(errkit.New(fmt.Sprintf("could not parse URL %s", target)), err) } hasTrailingSlash := httputil.HasTrailingSlash(target) diff --git a/pkg/protocols/headless/engine/page_actions.go b/pkg/protocols/headless/engine/page_actions.go index c051357d9..1a11bdc7f 100644 --- a/pkg/protocols/headless/engine/page_actions.go +++ b/pkg/protocols/headless/engine/page_actions.go @@ -23,7 +23,6 @@ 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" @@ -32,8 +31,8 @@ import ( ) var ( - errinvalidArguments = errorutil.New("invalid arguments provided") - ErrLFAccessDenied = errorutil.New("Use -allow-local-file-access flag to enable local file access") + errinvalidArguments = errkit.New("invalid arguments provided").Build() + ErrLFAccessDenied = errkit.New("Use -allow-local-file-access flag to enable local file access").Build() // ErrActionExecDealine is the error returned when alloted time for action execution exceeds ErrActionExecDealine = errkit.New("headless action execution deadline exceeded").SetKind(errkit.ErrKindDeadline).Build() ) @@ -60,7 +59,7 @@ func (p *Page) ExecuteActions(input *contextargs.Context, actions []*Action) (ou } if r := recover(); r != nil { - err = errorutil.New("panic on headless action: %v", r) + err = errkit.New(fmt.Sprintf("panic on headless action: %v", r)).Build() } }() @@ -73,7 +72,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, errorutil.NewWithErr(err).Msgf("error occurred while executing waitFunc") + return nil, errkit.Append(errkit.New("error occurred while executing waitFunc"), err) } } } @@ -401,7 +400,7 @@ func (p *Page) NavigateURL(action *Action, out ActionData) error { parsedURL, err := urlutil.ParseURL(url, true) if err != nil { - return errorutil.NewWithTag("headless", "failed to parse url %v while creating http request", url) + return errkit.New(fmt.Sprintf("headless: failed to parse url %v while creating http request", url)).Build() } // ===== parameter automerge ===== @@ -411,7 +410,7 @@ func (p *Page) NavigateURL(action *Action, out ActionData) error { parsedURL.Params = finalparams if err := p.page.Navigate(parsedURL.String()); err != nil { - return errorutil.NewWithErr(err).Msgf("could not navigate to url %s", parsedURL.String()) + return errkit.Append(errkit.New(fmt.Sprintf("could not navigate to url %s", parsedURL.String())), err) } p.updateLastNavigatedURL() @@ -525,14 +524,14 @@ func (p *Page) Screenshot(act *Action, out ActionData) error { to, err = fileutil.CleanPath(to) if err != nil { - return errorutil.New("could not clean output screenshot path %s", to) + return errkit.New(fmt.Sprintf("could not clean output screenshot path %s", to)).Build() } // allow if targetPath is child of current working directory if !protocolstate.IsLfaAllowed(p.options.Options) { cwd, err := os.Getwd() if err != nil { - return errorutil.NewWithErr(err).Msgf("could not get current working directory") + return errkit.Append(errkit.New("could not get current working directory"), err) } if !strings.HasPrefix(to, cwd) { @@ -551,7 +550,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 errorutil.NewWithErr(err).Msgf("failed to create directory while writing screenshot") + return errkit.Append(errkit.New("failed to create directory while writing screenshot"), err) } } @@ -563,7 +562,7 @@ func (p *Page) Screenshot(act *Action, out ActionData) error { if fileutil.FileExists(filePath) { // return custom error as overwriting files is not supported - return errorutil.NewWithTag("screenshot", "failed to write screenshot, file %v already exists", filePath) + return errkit.New(fmt.Sprintf("screenshot: failed to write screenshot, file %v already exists", filePath)).Build() } err = os.WriteFile(filePath, data, 0540) if err != nil { @@ -806,12 +805,12 @@ func (p *Page) WaitEvent(act *Action, out ActionData) (func() error, error) { gotType := proto.GetType(event) if gotType == nil { - return nil, errorutil.New("event %q does not exist", event) + return nil, errkit.New(fmt.Sprintf("event %q does not exist", event)).Build() } tmp, ok := reflect.New(gotType).Interface().(proto.Event) if !ok { - return nil, errorutil.New("event %q is not a page event", event) + return nil, errkit.New(fmt.Sprintf("event %q is not a page event", event)).Build() } waitEvent = tmp @@ -948,7 +947,7 @@ func (p *Page) getActionArg(action *Action, arg string) (string, error) { err = expressions.ContainsUnresolvedVariables(exprs...) if err != nil { - return "", errorutil.NewWithErr(err).Msgf("argument %q, value: %q", arg, argValue) + return "", errkit.Append(errkit.New(fmt.Sprintf("argument %q, value: %q", arg, argValue)), err) } argValue, err = expressions.Evaluate(argValue, p.variables) diff --git a/pkg/protocols/http/build_request.go b/pkg/protocols/http/build_request.go index 291168265..7dac41568 100644 --- a/pkg/protocols/http/build_request.go +++ b/pkg/protocols/http/build_request.go @@ -27,7 +27,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/types/scanstrategy" "github.com/projectdiscovery/rawhttp" "github.com/projectdiscovery/retryablehttp-go" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" readerutil "github.com/projectdiscovery/utils/reader" stringsutil "github.com/projectdiscovery/utils/strings" urlutil "github.com/projectdiscovery/utils/url" @@ -37,11 +37,17 @@ const ( ReqURLPatternKey = "req_url_pattern" ) -// ErrEvalExpression -var ( - ErrEvalExpression = errorutil.NewWithTag("expr", "could not evaluate helper expressions") - ErrUnresolvedVars = errorutil.NewWithFmt("unresolved variables `%v` found in request") -) +// 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() +} // generatedRequest is a single generated request wrapped for a template request type generatedRequest struct { @@ -193,7 +199,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.Wrap(err).WithTag("http") + return nil, ErrEvalExpression("http")(err) } } // finalVars contains allVars and any generator/fuzzing specific payloads @@ -210,7 +216,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.Wrap(err).WithTag("http") + return nil, ErrEvalExpression("http")(err) } if isRawRequest { @@ -219,7 +225,7 @@ func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context, reqURL, err := urlutil.ParseAbsoluteURL(reqData, true) if err != nil { - return nil, errorutil.NewWithTag("http", "failed to parse url %v while creating http request", reqData) + return nil, errkit.New(fmt.Sprintf("http: failed to parse url %v while creating http request", reqData)).Build() } // while merging parameters first preference is given to target params finalparams := parsed.Params @@ -252,7 +258,7 @@ func (r *requestGenerator) makeSelfContainedRequest(ctx context.Context, data st // evaluate request data, err := expressions.Evaluate(data, values) if err != nil { - return nil, ErrEvalExpression.Wrap(err).WithTag("self-contained") + return nil, ErrEvalExpression("self-contained")(err) } // If the request is a raw request, get the URL from the request // header and use it to make the request. @@ -275,7 +281,7 @@ func (r *requestGenerator) makeSelfContainedRequest(ctx context.Context, data st } if err := expressions.ContainsUnresolvedVariables(parts[1]); err != nil && !r.request.SkipVariablesCheck { - return nil, ErrUnresolvedVars.Msgf(parts[1]) + return nil, ErrUnresolvedVars(parts[1]) } parsed, err := urlutil.ParseURL(parts[1], true) @@ -289,19 +295,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.Wrap(err).WithTag("self-contained", "raw") + return nil, ErrEvalExpression("self-contained")(err) } 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.Msgf(data) + return nil, ErrUnresolvedVars(data) } urlx, err := urlutil.ParseURL(data, true) if err != nil { - return nil, errorutil.NewWithErr(err).Msgf("failed to parse %v in self contained request", data).WithTag("self-contained") + return nil, errkit.New(fmt.Sprintf("self-contained: failed to parse %v in self contained request: %s", data, err)).Build() } return r.generateHttpRequest(ctx, urlx, values, payloads) } @@ -312,7 +318,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.Wrap(err).Msgf("failed to evaluate while generating http request") + return nil, ErrEvalExpression("http")(err) } // Build a request on the specified URL req, err := retryablehttp.NewRequestFromURLWithContext(ctx, method, urlx, nil) @@ -341,7 +347,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, errorutil.NewWithErr(err).Msgf("failed to parse raw request") + return nil, errkit.Append(errkit.New("failed to parse raw request"), err) } // Unsafe option uses rawhttp library @@ -357,7 +363,7 @@ func (r *requestGenerator) generateRawRequest(ctx context.Context, rawRequest st } urlx, err := urlutil.ParseAbsoluteURL(rawRequestData.FullURL, true) if err != nil { - return nil, errorutil.NewWithErr(err).Msgf("failed to create request with url %v got %v", rawRequestData.FullURL, err).WithTag("raw") + return nil, errkit.New(fmt.Sprintf("raw: failed to create request with url %v got %v", rawRequestData.FullURL, err)).Build() } req, err := retryablehttp.NewRequestFromURLWithContext(ctx, rawRequestData.Method, urlx, rawRequestData.Data) if err != nil { @@ -414,7 +420,7 @@ func (r *requestGenerator) fillRequest(req *retryablehttp.Request, values map[st } value, err := expressions.Evaluate(value, values) if err != nil { - return nil, ErrEvalExpression.Wrap(err).Msgf("failed to evaluate while adding headers to request") + return nil, ErrEvalExpression("http")(err) } req.Header[header] = []string{value} if header == "Host" { @@ -435,7 +441,7 @@ func (r *requestGenerator) fillRequest(req *retryablehttp.Request, values map[st } body, err := expressions.Evaluate(body, values) if err != nil { - return nil, ErrEvalExpression.Wrap(err) + return nil, ErrEvalExpression("http")(err) } bodyReader, err := readerutil.NewReusableReadCloser([]byte(body)) if err != nil { diff --git a/pkg/protocols/http/raw/raw.go b/pkg/protocols/http/raw/raw.go index f6c427ad9..11454bb77 100644 --- a/pkg/protocols/http/raw/raw.go +++ b/pkg/protocols/http/raw/raw.go @@ -12,7 +12,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx" "github.com/projectdiscovery/rawhttp/client" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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, errorutil.NewWithErr(err).WithTag("raw").Msgf("failed to parse url %v from template", rawrequest.Path) + return nil, errkit.New(fmt.Sprintf("raw: failed to parse url %v from template: %s", rawrequest.Path, err)).Build() } 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, errorutil.NewWithTag("raw", "could not automergepath for template path %v", urlx.GetRelativePath()).Wrap(parseErr) + return nil, errkit.Append(errkit.New(fmt.Sprintf("raw: could not automergepath for template path %v", urlx.GetRelativePath())), 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, errorutil.NewWithErr(err).WithTag("raw").Msgf("failed to automerge %v from unsafe template", rawrequest.Path) + return nil, errkit.New(fmt.Sprintf("raw: failed to automerge %v from unsafe template: %s", rawrequest.Path, err)).Build() } 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, errorutil.NewWithTag("raw", "could not automergepath for template path %v", rawrequest.Path).Wrap(parseErr) + return nil, errkit.Append(errkit.New(fmt.Sprintf("raw: could not automergepath for template path %v", rawrequest.Path)), 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, errorutil.NewWithErr(err).Msgf("failed to parse url %v", req.Path) + return nil, errkit.Append(errkit.New(fmt.Sprintf("failed to parse url %v", req.Path)), err) } req.Path = urlx.GetRelativePath() req.FullURL = urlx.String() } else { if req.Path == "" { - return nil, errorutil.NewWithTag("self-contained-raw", "path cannot be empty in self contained request") + return nil, errkit.New("self-contained-raw: path cannot be empty in self contained request").Build() } // given url is relative construct one using Host Header if _, ok := req.Headers["Host"]; !ok { - return nil, errorutil.NewWithTag("self-contained-raw", "host header is required for relative path") + return nil, errkit.New("self-contained-raw: host header is required for relative path").Build() } // 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) diff --git a/pkg/protocols/http/signer/aws-sign.go b/pkg/protocols/http/signer/aws-sign.go index 0da4902c3..bf6e15d3e 100644 --- a/pkg/protocols/http/signer/aws-sign.go +++ b/pkg/protocols/http/signer/aws-sign.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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 errorutil.NewWithErr(err).Msgf("failed to sign http request using aws v4 signer") + return errkit.Append(errkit.New("failed to sign http request using aws v4 signer"), err) } // add x-amz-content-sha256 header to request request.Header.Set("x-amz-content-sha256", contentHash) diff --git a/pkg/protocols/http/utils.go b/pkg/protocols/http/utils.go index 90b2e8446..547b32dab 100644 --- a/pkg/protocols/http/utils.go +++ b/pkg/protocols/http/utils.go @@ -1,12 +1,13 @@ package http import ( + "fmt" "io" "strings" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators" "github.com/projectdiscovery/rawhttp" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) // dump creates a dump of the http request in form of a byte slice @@ -15,14 +16,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, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", req.request.String()) + return nil, errkit.New(fmt.Sprintf("http: could not dump request: %v: %s", req.request.String(), err)).Build() } 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, errorutil.NewWithErr(err).WithTag("http").Msgf("could not dump request: %v", reqURL) + return nil, errkit.New(fmt.Sprintf("http: could not dump request: %v: %s", reqURL, err)).Build() } return bin, nil } diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index fc5b30b98..573855ab5 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -34,7 +34,6 @@ 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" @@ -128,14 +127,14 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { } } if err := compiled.Compile(); err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not compile operators got %v", err) + return errkit.New(fmt.Sprintf("%s: could not compile operators got %v", request.TemplateID, err)).Build() } request.CompiledOperators = compiled } // "Port" is a special variable and it should not contains any dsl expressions if strings.Contains(request.getPort(), "{{") { - return errorutil.NewWithTag(request.TemplateID, "'Port' variable cannot contain any dsl expressions") + return errkit.New(fmt.Sprintf("%s: 'Port' variable cannot contain any dsl expressions", request.TemplateID)).Build() } if request.Init != "" { @@ -219,11 +218,11 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { initCompiled, err := compiler.SourceAutoMode(request.Init, false) if err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not compile init code: %s", err) + return errkit.New(fmt.Sprintf("%s: could not compile init code: %s", request.TemplateID, err)).Build() } result, err := request.options.JsCompiler.ExecuteWithOptions(initCompiled, args, opts) if err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not execute pre-condition: %s", err) + return errkit.New(fmt.Sprintf("%s: could not execute pre-condition: %s", request.TemplateID, err)).Build() } if types.ToString(result["error"]) != "" { gologger.Warning().Msgf("[%s] Init failed with error %v\n", request.TemplateID, result["error"]) @@ -240,7 +239,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { if request.PreCondition != "" { preConditionCompiled, err := compiler.SourceAutoMode(request.PreCondition, false) if err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not compile pre-condition: %s", err) + return errkit.New(fmt.Sprintf("%s: could not compile pre-condition: %s", request.TemplateID, err)).Build() } request.preConditionCompiled = preConditionCompiled } @@ -249,7 +248,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { if request.Code != "" { scriptCompiled, err := compiler.SourceAutoMode(request.Code, false) if err != nil { - return errorutil.NewWithTag(request.TemplateID, "could not compile javascript code: %s", err) + return errkit.New(fmt.Sprintf("%s: could not compile javascript code: %s", request.TemplateID, err)).Build() } request.scriptCompiled = scriptCompiled } diff --git a/pkg/protocols/network/network.go b/pkg/protocols/network/network.go index be3c85cd6..f1adc90c2 100644 --- a/pkg/protocols/network/network.go +++ b/pkg/protocols/network/network.go @@ -1,6 +1,7 @@ package network import ( + "fmt" "strconv" "strings" @@ -12,7 +13,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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" fileutil "github.com/projectdiscovery/utils/file" ) @@ -196,10 +197,10 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { } portInt, err := strconv.Atoi(port) if err != nil { - return errorutil.NewWithErr(err).Msgf("could not parse port %v from '%s'", port, request.Port) + return errkit.Append(errkit.New(fmt.Sprintf("could not parse port %v from '%s'", port, request.Port)), err) } if portInt < 1 || portInt > 65535 { - return errorutil.NewWithTag(request.TemplateID, "port %v is not in valid range", portInt) + return errkit.New(fmt.Sprintf("%s: port %v is not in valid range", request.TemplateID, portInt)).Build() } request.ports = append(request.ports, port) } diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index 24071763e..63e1bfb59 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithErr(err).Msgf("could not read response from connection") + return errkit.Append(errkit.New("could not read response from connection"), err) } responseBuilder.Write(buffer) diff --git a/pkg/protocols/ssl/ssl.go b/pkg/protocols/ssl/ssl.go index 72d666422..aa4a02616 100644 --- a/pkg/protocols/ssl/ssl.go +++ b/pkg/protocols/ssl/ssl.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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 errorutil.NewWithTag("ssl", "could not get network client").Wrap(err) + return errkit.Append(errkit.New("ssl: could not get network client"), 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 errorutil.NewWithTag(request.TemplateID, "template %v does not contain valid scan-mode", request.TemplateID) + return errkit.New(fmt.Sprintf("%s: template %v does not contain valid scan-mode", request.TemplateID, request.TemplateID)).Build() 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 errorutil.NewWithTag(request.TemplateID, "could not create tlsx service") + return errkit.New(fmt.Sprintf("%s: could not create tlsx service", request.TemplateID)).Build() } 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 errorutil.NewWithTag(request.TemplateID, "could not compile operators got %v", err) + return errkit.New(fmt.Sprintf("%s: could not compile operators got %v", request.TemplateID, err)).Build() } 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 errorutil.NewWithErr(err).Msgf("could not split input host port") + return errkit.Append(errkit.New("could not split input host port"), err) } 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 errorutil.NewWithTag(request.TemplateID, "could not connect to server").Wrap(err) + return errkit.Append(errkit.New(fmt.Sprintf("%s: could not connect to server", request.TemplateID)), 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 errorutil.NewWithTag("ssl", "response cannot be parsed into a struct: %v", response) + return errkit.New(fmt.Sprintf("ssl: response cannot be parsed into a struct: %v", response)).Build() } // 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 errorutil.NewWithTag("ssl", "certificate response cannot be parsed into a struct: %v", response.CertificateResponse) + return errkit.New(fmt.Sprintf("ssl: certificate response cannot be parsed into a struct: %v", response.CertificateResponse)).Build() } responseParsed = structs.New(response.CertificateResponse) diff --git a/pkg/reporting/exporters/markdown/util/markdown_utils.go b/pkg/reporting/exporters/markdown/util/markdown_utils.go index b9a674405..2ec5d8f9f 100644 --- a/pkg/reporting/exporters/markdown/util/markdown_utils.go +++ b/pkg/reporting/exporters/markdown/util/markdown_utils.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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 "", errorutil.New("No headers provided") + return "", errkit.New("No headers provided").Build() } 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 "", errorutil.New("Too many columns for the given headers") + return "", errkit.New("Too many columns for the given headers").Build() } } diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index 100f35743..30de6ad87 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" 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, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation) + return nil, errkit.Append(ErrReportingClientCreation, err) } 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, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation) + return nil, errkit.Append(ErrReportingClientCreation, err) } 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, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation) + return nil, errkit.Append(ErrReportingClientCreation, err) } 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, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation) + return nil, errkit.Append(ErrReportingClientCreation, err) } 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, errorutil.NewWithErr(err).Wrap(ErrReportingClientCreation) + return nil, errkit.Append(ErrReportingClientCreation, err) } client.trackers = append(client.trackers, tracker) } if options.MarkdownExporter != nil { exporter, err := markdown.New(options.MarkdownExporter) if err != nil { - return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } client.exporters = append(client.exporters, exporter) } if options.SarifExporter != nil { exporter, err := sarif.New(options.SarifExporter) if err != nil { - return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } client.exporters = append(client.exporters, exporter) } if options.JSONExporter != nil { exporter, err := json_exporter.New(options.JSONExporter) if err != nil { - return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } client.exporters = append(client.exporters, exporter) } if options.JSONLExporter != nil { exporter, err := jsonl.New(options.JSONLExporter) if err != nil { - return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } 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, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } 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, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } client.exporters = append(client.exporters, exporter) } if options.MongoDBExporter != nil { exporter, err := mongo.New(options.MongoDBExporter) if err != nil { - return nil, errorutil.NewWithErr(err).Wrap(ErrExportClientCreation) + return nil, errkit.Append(ErrExportClientCreation, err) } client.exporters = append(client.exporters, exporter) } @@ -227,7 +227,7 @@ func CreateConfigIfNotExists() error { } reportingFile, err := os.Create(reportingConfig) if err != nil { - return errorutil.NewWithErr(err).Msgf("could not create config file") + return errkit.Append(errkit.New("could not create config file"), err) } defer func() { _ = reportingFile.Close() diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index fdb612a96..6554e8cde 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" stringsutil "github.com/projectdiscovery/utils/strings" ) @@ -480,7 +480,7 @@ func parseTemplate(data []byte, srcOptions *protocols.ExecutorOptions) (*Templat } } if err != nil { - return nil, errorutil.NewWithErr(err).Msgf("failed to parse %s", template.Path) + return nil, errkit.Append(errkit.New(fmt.Sprintf("failed to parse %s", template.Path)), err) } 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, errorutil.NewWithErr(err).Msgf("failed to load file refs for %s", template.ID) + return nil, errkit.Append(errkit.New(fmt.Sprintf("failed to load file refs for %s", template.ID)), err) } if err := template.compileProtocolRequests(template.Options); err != nil { diff --git a/pkg/templates/parser.go b/pkg/templates/parser.go index 3a2cabc2a..bf24308e7 100644 --- a/pkg/templates/parser.go +++ b/pkg/templates/parser.go @@ -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.Msgf(templatePath, templateParseError) + return false, ErrCouldNotLoadTemplate(templatePath, templateParseError.Error()) } 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.Msgf(templatePath, validationError) + return false, ErrCouldNotLoadTemplate(templatePath, validationError.Error()) } ret, err := isTemplateInfoMetadataMatch(tagFilter, template, extraTags) if err != nil { checkOpenFileError(err) - return ret, ErrCouldNotLoadTemplate.Msgf(templatePath, err) + return ret, ErrCouldNotLoadTemplate(templatePath, err.Error()) } // 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.Msgf(templatePath, validationWarning) + return ret, ErrCouldNotLoadTemplate(templatePath, validationWarning.Error()) } } return ret, nil diff --git a/pkg/templates/parser_error.go b/pkg/templates/parser_error.go index 98c9e25d7..eaf174cbc 100644 --- a/pkg/templates/parser_error.go +++ b/pkg/templates/parser_error.go @@ -1,13 +1,28 @@ package templates import ( - errorutil "github.com/projectdiscovery/utils/errors" + "fmt" + + "github.com/projectdiscovery/utils/errkit" ) -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") -) +// 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() +} diff --git a/pkg/templates/parser_test.go b/pkg/templates/parser_test.go index 4ec35b973..9b405d025 100644 --- a/pkg/templates/parser_test.go +++ b/pkg/templates/parser_test.go @@ -41,7 +41,7 @@ func TestLoadTemplate(t *testing.T) { name: "emptyTemplate", template: &Template{}, isValid: false, - expectedErr: errors.New("mandatory 'name' field is missing\nmandatory 'author' field is missing\nmandatory 'id' field is missing"), + 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\\\"\""), }, { name: "emptyNameWithInvalidID", @@ -52,7 +52,7 @@ func TestLoadTemplate(t *testing.T) { SeverityHolder: severity.Holder{Severity: severity.Medium}, }, }, - expectedErr: errors.New("mandatory 'name' field is missing\ninvalid field format for 'id' (allowed format is ^([a-zA-Z0-9]+[-_])*[a-zA-Z0-9]+$)"), + 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]+$)\\\"\""), }, { name: "emptySeverity", diff --git a/pkg/templates/parser_validate.go b/pkg/templates/parser_validate.go index 346683550..3911bbb22 100644 --- a/pkg/templates/parser_validate.go +++ b/pkg/templates/parser_validate.go @@ -15,17 +15,17 @@ func validateTemplateMandatoryFields(template *Template) error { var validateErrors []error if utils.IsBlank(info.Name) { - validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt.Msgf("name")) + validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("name")) } if info.Authors.IsEmpty() { - validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt.Msgf("author")) + validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("author")) } if template.ID == "" { - validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt.Msgf("id")) + validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("id")) } else if !ReTemplateID.MatchString(template.ID) { - validateErrors = append(validateErrors, ErrInvalidField.Msgf("id", ReTemplateID.String())) + validateErrors = append(validateErrors, ErrInvalidField("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.Msgf("severity")) + warnings = append(warnings, ErrWarningFieldMissing("severity")) } if len(warnings) > 0 { diff --git a/pkg/templates/signer/default.go b/pkg/templates/signer/default.go index 16900bd08..174bda18c 100644 --- a/pkg/templates/signer/default.go +++ b/pkg/templates/signer/default.go @@ -4,7 +4,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" "github.com/projectdiscovery/nuclei/v3/pkg/keys" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) // 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 errorutil.New("signer is nil") + return errkit.New("signer is nil").Build() } DefaultTemplateVerifiers = append(DefaultTemplateVerifiers, s) return nil diff --git a/pkg/templates/signer/tmpl_signer.go b/pkg/templates/signer/tmpl_signer.go index 35536ab6e..bb3d26c48 100644 --- a/pkg/templates/signer/tmpl_signer.go +++ b/pkg/templates/signer/tmpl_signer.go @@ -16,7 +16,7 @@ import ( "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) 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 "", errorutil.NewWithTag("signer", "re-signing code templates are not allowed for security reasons.") + return "", errkit.New("signer: re-signing code templates are not allowed for security reasons.").Build() } if len(arr) == 3 { // signature has fragment verify if it is equal to current fragment fragment := t.GetUserFragment() if fragment != arr[2] { - return "", errorutil.NewWithTag("signer", "re-signing code templates are not allowed for security reasons.") + return "", errkit.New("signer: re-signing code templates are not allowed for security reasons.").Build() } } } diff --git a/pkg/templates/template_sign.go b/pkg/templates/template_sign.go index d9a1417eb..e6647a335 100644 --- a/pkg/templates/template_sign.go +++ b/pkg/templates/template_sign.go @@ -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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" ) // Due to file references in sensitive fields of template @@ -28,7 +28,7 @@ var ( _ = protocolstate.Init(defaultOpts) _ = protocolinit.Init(defaultOpts) }) - ErrNotATemplate = errorutil.NewWithTag("signer", "given filePath is not a template") + ErrNotATemplate = errkit.New("signer: given filePath is not a template").Build() ) // 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 errorutil.NewWithErr(err).Msgf("failed to get template from disk") + return errkit.Append(errkit.New("failed to get template from disk"), err) } 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, errorutil.NewWithErr(err).Msgf("failed to parse template") + return nil, bin, errkit.Append(errkit.New("failed to parse template"), err) } return template, bin, nil } diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index fbbfd44e9..418234751 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -2,6 +2,7 @@ package templates import ( + "fmt" "io" "path/filepath" "strconv" @@ -24,7 +25,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/utils" "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" "github.com/projectdiscovery/nuclei/v3/pkg/workflows" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" fileutil "github.com/projectdiscovery/utils/file" "go.uber.org/multierr" "gopkg.in/yaml.v2" @@ -325,14 +326,14 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error *template = Template(*alias) if !ReTemplateID.MatchString(template.ID) { - return errorutil.New("template id must match expression %v", ReTemplateID).WithTag("invalid template") + return errkit.New(fmt.Sprintf("invalid template: template id must match expression %v", ReTemplateID)).Build() } info := template.Info if utils.IsBlank(info.Name) { - return errorutil.New("no template name field provided").WithTag("invalid template") + return errkit.New("invalid template: no template name field provided").Build() } if info.Authors.IsEmpty() { - return errorutil.New("no template author field provided").WithTag("invalid template") + return errkit.New("invalid template: no template author field provided").Build() } if len(template.RequestsHTTP) > 0 || len(template.RequestsNetwork) > 0 { @@ -340,10 +341,10 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error } if len(alias.RequestsHTTP) > 0 && len(alias.RequestsWithHTTP) > 0 { - return errorutil.New("use http or requests, both are not supported").WithTag("invalid template") + return errkit.New("invalid template: use http or requests, both are not supported").Build() } if len(alias.RequestsNetwork) > 0 && len(alias.RequestsWithTCP) > 0 { - return errorutil.New("use tcp or network, both are not supported").WithTag("invalid template") + return errkit.New("invalid template: use tcp or network, both are not supported").Build() } if len(alias.RequestsWithHTTP) > 0 { template.RequestsHTTP = alias.RequestsWithHTTP @@ -361,7 +362,7 @@ func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error var tempmap yaml.MapSlice err = unmarshal(&tempmap) if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to unmarshal multi protocol template %s", template.ID) + return errkit.Append(errkit.New(fmt.Sprintf("failed to unmarshal multi protocol template %s", template.ID)), err) } arr := []string{} for _, v := range tempmap { @@ -545,7 +546,7 @@ func (template *Template) UnmarshalJSON(data []byte) error { var tempMap map[string]interface{} err = json.Unmarshal(data, &tempMap) if err != nil { - return errorutil.NewWithErr(err).Msgf("failed to unmarshal multi protocol template %s", template.ID) + return errkit.Append(errkit.New(fmt.Sprintf("failed to unmarshal multi protocol template %s", template.ID)), err) } arr := []string{} for k := range tempMap { diff --git a/pkg/tmplexec/flow/flow_executor.go b/pkg/tmplexec/flow/flow_executor.go index 226a0c432..860e96292 100644 --- a/pkg/tmplexec/flow/flow_executor.go +++ b/pkg/tmplexec/flow/flow_executor.go @@ -16,16 +16,16 @@ import ( "github.com/kitabisa/go-ci" "github.com/projectdiscovery/nuclei/v3/pkg/types" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" fileutil "github.com/projectdiscovery/utils/file" mapsutil "github.com/projectdiscovery/utils/maps" "go.uber.org/multierr" ) -var ( - // ErrInvalidRequestID is a request id error - ErrInvalidRequestID = errorutil.NewWithFmt("[%s] invalid request id '%s' provided") -) +// 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() +} // 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 errorutil.NewWithErr(err).Msgf("failed to execute flow\n%v\n", f.options.Flow) + return errkit.Append(errkit.New(fmt.Sprintf("failed to execute flow\n%v\n", f.options.Flow)), err) } runtimeErr := f.GetRuntimeErrors() if runtimeErr != nil { ctx.LogError(runtimeErr) - return errorutil.NewWithErr(runtimeErr).Msgf("got following errors while executing flow") + return errkit.Append(errkit.New("got following errors while executing flow"), runtimeErr) } 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, errorutil.NewWithErr(err).Msgf("failed to execute %v protocol", proto)) + errs = append(errs, errkit.Append(errkit.New(fmt.Sprintf("failed to execute %v protocol", proto)), err)) } return multierr.Combine(errs...) } diff --git a/pkg/tmplexec/flow/flow_internal.go b/pkg/tmplexec/flow/flow_internal.go index 9a8d807cc..249f324c6 100644 --- a/pkg/tmplexec/flow/flow_internal.go +++ b/pkg/tmplexec/flow/flow_internal.go @@ -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.Msgf(f.options.TemplateID, id)); err != nil { + if err := f.allErrs.Set(opts.protoName+":"+id, ErrInvalidRequestID(f.options.TemplateID, id)); err != nil { f.ctx.LogError(fmt.Errorf("failed to store flow runtime errors got %v", err)) } return matcherStatus.Load() diff --git a/pkg/types/types.go b/pkg/types/types.go index 656ff8447..4d009db51 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "io" "os" "path/filepath" @@ -14,7 +15,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" - errorutil "github.com/projectdiscovery/utils/errors" + "github.com/projectdiscovery/utils/errkit" fileutil "github.com/projectdiscovery/utils/file" folderutil "github.com/projectdiscovery/utils/folder" unitutils "github.com/projectdiscovery/utils/unit" @@ -830,7 +831,7 @@ func (options *Options) defaultLoadHelperFile(helperFile, templatePath string, c } f, err := os.Open(helperFile) if err != nil { - return nil, errorutil.NewWithErr(err).Msgf("could not open file %v", helperFile) + return nil, errkit.Append(errkit.New(fmt.Sprintf("could not open file %v", helperFile)), err) } return f, nil } @@ -855,12 +856,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 "", errorutil.NewWithErr(err).Msgf("could not clean helper file path %v", helperFilePath) + return "", errkit.Append(errkit.New(fmt.Sprintf("could not clean helper file path %v", helperFilePath)), err) } templatePath, err = fileutil.CleanPath(templatePath) if err != nil { - return "", errorutil.NewWithErr(err).Msgf("could not clean template path %v", templatePath) + return "", errkit.Append(errkit.New(fmt.Sprintf("could not clean template path %v", templatePath)), err) } // As per rule 2, if template and helper file exist in same directory or helper file existed in any child dir of template dir @@ -871,7 +872,7 @@ func (o *Options) GetValidAbsPath(helperFilePath, templatePath string) (string, } // all other cases are denied - return "", errorutil.New("access to helper file %v denied", helperFilePath) + return "", errkit.New(fmt.Sprintf("access to helper file %v denied", helperFilePath)).Build() } // SetExecutionID sets the execution ID for the options From 5c15c777779aa813e2f20cef147e26b85b314946 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 21 Aug 2025 22:02:47 +0200 Subject: [PATCH 084/135] adding vnc auth --- go.mod | 1 + go.sum | 2 + pkg/js/libs/vnc/vnc.go | 84 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 2fd4ee3b5..f6b30c09c 100644 --- a/go.mod +++ b/go.mod @@ -144,6 +144,7 @@ require ( github.com/alecthomas/kingpin/v2 v2.4.0 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/alexsnet/go-vnc v0.1.0 // indirect github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect diff --git a/go.sum b/go.sum index 5fa540e33..298de217d 100644 --- a/go.sum +++ b/go.sum @@ -124,6 +124,8 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/alexsnet/go-vnc v0.1.0 h1:vBCwPNy79WEL8V/Z5A0ngEFCvTWBAjmS048lkR2rdmY= +github.com/alexsnet/go-vnc v0.1.0/go.mod h1:bbRsg41Sh3zvrnWsw+REKJVGZd8Of2+S0V1G0ZaBhlU= github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs= github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 h1:8PmGpDEZl9yDpcdEr6Odf23feCxK3LNUNMxjXg41pZQ= diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index bd28ad692..2798cc639 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -7,9 +7,11 @@ import ( "strconv" "time" + vnclib "github.com/alexsnet/go-vnc" "github.com/praetorian-inc/fingerprintx/pkg/plugins" - "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/vnc" + vncplugin "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/vnc" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" + stringsutil "github.com/projectdiscovery/utils/strings" ) type ( @@ -24,8 +26,86 @@ type ( IsVNC bool Banner string } + + // VNCClient is a client for VNC servers. + // @example + // ```javascript + // const vnc = require('nuclei/vnc'); + // const client = new vnc.VNCClient(); + // const connected = client.Connect('acme.com', 5900, 'password'); + // log(toJSON(connected)); + // ``` + VNCClient struct{} ) +// Connect connects to VNC server using given password. +// If connection and authentication is successful, it returns true. +// If connection or authentication is unsuccessful, it returns false and error. +// The connection is closed after the function returns. +// @example +// ```javascript +// const vnc = require('nuclei/vnc'); +// const client = new vnc.VNCClient(); +// const connected = client.Connect('acme.com', 5900, 'password'); +// ``` +func (c *VNCClient) Connect(ctx context.Context, host string, port int, password string) (bool, error) { + executionId := ctx.Value("executionId").(string) + return connect(executionId, host, port, password) +} + +// connect attempts to authenticate with a VNC server using the given password +func connect(executionId string, host string, port int, password string) (bool, error) { + if host == "" || port <= 0 { + return false, fmt.Errorf("invalid host or port") + } + if !protocolstate.IsHostAllowed(executionId, host) { + // host is not valid according to network policy + return false, protocolstate.ErrHostDenied(host) + } + + dialer := protocolstate.GetDialersWithId(executionId) + if dialer == nil { + return false, fmt.Errorf("dialers not initialized for %s", executionId) + } + + conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port))) + if err != nil { + return false, err + } + defer func() { + _ = conn.Close() + }() + + // Set connection timeout + conn.SetDeadline(time.Now().Add(10 * time.Second)) + + // Create VNC client config with password + vncConfig := vnclib.NewClientConfig(password) + + // Attempt to connect and authenticate + _, err = vnclib.Connect(context.TODO(), conn, vncConfig) + if err != nil { + // Check for specific authentication errors + if isAuthError(err) { + return false, nil // Authentication failed, but connection succeeded + } + return false, err // Connection or other error + } + + return true, nil +} + +// isAuthError checks if the error is an authentication failure +func isAuthError(err error) bool { + if err == nil { + return false + } + + // Check for common VNC authentication error messages + errStr := err.Error() + return stringsutil.ContainsAny(errStr, "authentication", "auth", "password", "invalid", "failed") +} + // IsVNC checks if a host is running a VNC server. // It returns a boolean indicating if the host is running a VNC server // and the banner of the VNC server. @@ -57,7 +137,7 @@ func isVNC(executionId string, host string, port int) (IsVNCResponse, error) { _ = conn.Close() }() - vncPlugin := vnc.VNCPlugin{} + vncPlugin := vncplugin.VNCPlugin{} service, err := vncPlugin.Run(conn, timeout, plugins.Target{Host: host}) if err != nil { return resp, err From b41f4d97d68121fc5ff0606f6c35bcad7f02f2d8 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 21 Aug 2025 22:04:55 +0200 Subject: [PATCH 085/135] gen go+js --- pkg/js/generated/go/libvnc/vnc.go | 1 + pkg/js/generated/ts/vnc.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/js/generated/go/libvnc/vnc.go b/pkg/js/generated/go/libvnc/vnc.go index 625f3776d..fa060ec14 100644 --- a/pkg/js/generated/go/libvnc/vnc.go +++ b/pkg/js/generated/go/libvnc/vnc.go @@ -21,6 +21,7 @@ func init() { // Objects / Classes "IsVNCResponse": gojs.GetClassConstructor[lib_vnc.IsVNCResponse](&lib_vnc.IsVNCResponse{}), + "VNCClient": gojs.GetClassConstructor[lib_vnc.VNCClient](&lib_vnc.VNCClient{}), }, ).Register() } diff --git a/pkg/js/generated/ts/vnc.ts b/pkg/js/generated/ts/vnc.ts index 870151e2b..f74edb894 100755 --- a/pkg/js/generated/ts/vnc.ts +++ b/pkg/js/generated/ts/vnc.ts @@ -33,3 +33,34 @@ export interface IsVNCResponse { Banner?: string, } +/** + * VNCClient is a client for VNC servers. + * @example + * ```javascript + * const vnc = require('nuclei/vnc'); + * const client = new vnc.VNCClient(); + * ``` + */ +export class VNCClient { + + + // Constructor of VNCClient + constructor() {} + + /** + * Connect connects to VNC server using given password. + * If connection and authentication is successful, it returns true. + * If connection or authentication is unsuccessful, it returns false and error. + * The connection is closed after the function returns. + * @example + * ```javascript + * const vnc = require('nuclei/vnc'); + * const client = new vnc.VNCClient(); + * const connected = client.Connect('acme.com', 5900, 'password'); + * ``` + */ + public Connect(host: string, port: number, password: string): boolean | null { + return null; + } +} + From 6b358b39a37046d9553de7022aeafb9a67ea1d43 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 21 Aug 2025 23:38:58 +0200 Subject: [PATCH 086/135] lint --- pkg/js/libs/vnc/vnc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index 2798cc639..c1aaf8103 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -77,7 +77,7 @@ func connect(executionId string, host string, port int, password string) (bool, }() // Set connection timeout - conn.SetDeadline(time.Now().Add(10 * time.Second)) + _ = conn.SetDeadline(time.Now().Add(10 * time.Second)) // Create VNC client config with password vncConfig := vnclib.NewClientConfig(password) From 30e520754b36fce298ce09b86a9c9fb58afbd79a Mon Sep 17 00:00:00 2001 From: Ice3man Date: Fri, 22 Aug 2025 20:25:07 +0530 Subject: [PATCH 087/135] feat: fixed output event for skipped hosts (#6415) * feat: fixed output event for skipped hosts * misc --- pkg/operators/matchers/match.go | 3 +-- pkg/output/output.go | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/operators/matchers/match.go b/pkg/operators/matchers/match.go index e74270ef1..78bd40175 100644 --- a/pkg/operators/matchers/match.go +++ b/pkg/operators/matchers/match.go @@ -8,7 +8,6 @@ import ( "github.com/antchfx/htmlquery" "github.com/antchfx/xmlquery" - dslRepo "github.com/projectdiscovery/dsl" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/expressions" @@ -316,7 +315,7 @@ func (m *Matcher) ignoreErr(err error) bool { if showDSLErr { return false } - if stringsutil.ContainsAny(err.Error(), "No parameter", dslRepo.ErrParsingArg.Error()) { + if stringsutil.ContainsAny(err.Error(), "No parameter", "error parsing argument value") { return true } return false diff --git a/pkg/output/output.go b/pkg/output/output.go index 571bff782..f7909320e 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -295,6 +295,10 @@ func (w *StandardWriter) ResultCount() int { // Write writes the event to file and/or screen. func (w *StandardWriter) Write(event *ResultEvent) error { + if event.Error != "" && !w.matcherStatus { + return nil + } + // Enrich the result event with extra metadata on the template-path and url. if event.TemplatePath != "" { event.Template, event.TemplateURL = utils.TemplatePathURL(types.ToString(event.TemplatePath), types.ToString(event.TemplateID), event.TemplateVerifier) From 00f4595f0b8803043b1322c7f6f8ab6ea00d8425 Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Fri, 22 Aug 2025 20:27:44 +0530 Subject: [PATCH 088/135] version update --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index a9de026d8..b820dc199 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -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.9` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From 5e9ada23b25177311c11f968edb2bf9cf0b5ab6d Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 23 Aug 2025 19:51:23 +0530 Subject: [PATCH 089/135] Update constants.go --- pkg/catalog/config/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/catalog/config/constants.go b/pkg/catalog/config/constants.go index b820dc199..f7fca13bf 100644 --- a/pkg/catalog/config/constants.go +++ b/pkg/catalog/config/constants.go @@ -31,7 +31,7 @@ const ( CLIConfigFileName = "config.yaml" ReportingConfigFilename = "reporting-config.yaml" // Version is the current version of nuclei - Version = `v3.4.9` + Version = `v3.4.10` // Directory Names of custom templates CustomS3TemplatesDirName = "s3" CustomGitHubTemplatesDirName = "github" From 309018fbf40ab4161d3d15c572468747e3e4479c Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:31:23 +0700 Subject: [PATCH 090/135] fix: segfault in template caching logic (#6421) * fix: segfault in template caching logic when templates had no executable requests after option updates. the cached templates could end up with 0 requests and no flow execution path, resulting in a nil engine pointer that was later derefer w/o validation. bug seq: caching template (w/ valid requests) -> get cached template -> `*ExecutorOptions.Options` copied and modified (inconsistent) -> requests updated (with new options -- some may be invalid, and without recompile) -> template returned w/o validation -> `compileProtocolRequests` -> `NewTemplateExecuter` receive empty requests + empty flow = nil engine -> `*TemplateExecuter.{Compile,Execute}` invoked on nil engine = panic. RCA: 1. `*ExecutorOptions.ApplyNewEngineOptions` overwriting many fields. 2. copy op pointless; create a copy of options and then immediately replace it with original pointer. 3. missing executable requests validation after cached templates is reconstructed with updated options. Thus, this affected `--automatic-scan` mode where tech detection templates often have conditional requests that may be filtered based on runtime options. Fixes #6417 Signed-off-by: Dwi Siswanto * fix(templates): recompile workflow with `tplCopy.Options` Signed-off-by: Dwi Siswanto * fix(templates): strengthen cache hit guard Signed-off-by: Dwi Siswanto * fix(protocols): skips template-specific fields Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- pkg/protocols/protocols.go | 19 ------------ pkg/templates/compile.go | 63 +++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/pkg/protocols/protocols.go b/pkg/protocols/protocols.go index 702aa5729..c3ee5c19c 100644 --- a/pkg/protocols/protocols.go +++ b/pkg/protocols/protocols.go @@ -447,21 +447,8 @@ func (e *ExecutorOptions) ApplyNewEngineOptions(n *ExecutorOptions) { return } - // The types.Options include the ExecutionID among other things e.Options = n.Options.Copy() - - // Keep the template-specific fields, but replace the rest - /* - e.TemplateID = n.TemplateID - e.TemplatePath = n.TemplatePath - e.TemplateInfo = n.TemplateInfo - e.TemplateVerifier = n.TemplateVerifier - e.RawTemplate = n.RawTemplate - e.Variables = n.Variables - e.Constants = n.Constants - */ e.Output = n.Output - e.Options = n.Options e.IssuesClient = n.IssuesClient e.Progress = n.Progress e.RateLimiter = n.RateLimiter @@ -470,8 +457,6 @@ func (e *ExecutorOptions) ApplyNewEngineOptions(n *ExecutorOptions) { e.Browser = n.Browser e.Interactsh = n.Interactsh e.HostErrorsCache = n.HostErrorsCache - e.StopAtFirstMatch = n.StopAtFirstMatch - e.ExcludeMatchers = n.ExcludeMatchers e.InputHelper = n.InputHelper e.FuzzParamsFrequency = n.FuzzParamsFrequency e.FuzzStatsDB = n.FuzzStatsDB @@ -479,10 +464,6 @@ func (e *ExecutorOptions) ApplyNewEngineOptions(n *ExecutorOptions) { e.Colorizer = n.Colorizer e.WorkflowLoader = n.WorkflowLoader e.ResumeCfg = n.ResumeCfg - e.ProtocolType = n.ProtocolType - e.Flow = n.Flow - e.IsMultiProtocol = n.IsMultiProtocol - e.templateCtxStore = n.templateCtxStore e.JsCompiler = n.JsCompiler e.AuthProvider = n.AuthProvider e.TemporaryDirectory = n.TemporaryDirectory diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index 6554e8cde..8a8d69675 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -64,6 +64,13 @@ func Parse(filePath string, preprocessor Preprocessor, options *protocols.Execut newBase.TemplateInfo = tplCopy.Options.TemplateInfo newBase.TemplateVerifier = tplCopy.Options.TemplateVerifier newBase.RawTemplate = tplCopy.Options.RawTemplate + + if tplCopy.Options.Variables.Len() > 0 { + newBase.Variables = tplCopy.Options.Variables + } + if len(tplCopy.Options.Constants) > 0 { + newBase.Constants = tplCopy.Options.Constants + } tplCopy.Options = newBase tplCopy.Options.ApplyNewEngineOptions(options) @@ -156,12 +163,16 @@ func Parse(filePath string, preprocessor Preprocessor, options *protocols.Execut // Compile the workflow request if len(template.Workflows) > 0 { compiled := &template.Workflow - compileWorkflow(filePath, preprocessor, options, compiled, options.WorkflowLoader) + compileWorkflow(filePath, preprocessor, tplCopy.Options, compiled, tplCopy.Options.WorkflowLoader) template.CompiledWorkflow = compiled - template.CompiledWorkflow.Options = options + template.CompiledWorkflow.Options = tplCopy.Options } - // options.Logger.Error().Msgf("returning cached template %s after recompiling %d requests", tplCopy.Options.TemplateID, tplCopy.Requests()) - return template, nil + + if isCachedTemplateValid(template) { + // options.Logger.Error().Msgf("returning cached template %s after recompiling %d requests", tplCopy.Options.TemplateID, tplCopy.Requests()) + return template, nil + } + // else: fallthrough to re-parse template from scratch } } @@ -579,6 +590,50 @@ func parseTemplate(data []byte, srcOptions *protocols.ExecutorOptions) (*Templat return template, nil } +// isCachedTemplateValid validates that a cached template is still usable after +// option updates +func isCachedTemplateValid(template *Template) bool { + // no requests or workflows + if template.Requests() == 0 && len(template.Workflows) == 0 { + return false + } + + // options not initialized + if template.Options == nil { + return false + } + + // executer not available for non-workflow template + if len(template.Workflows) == 0 && template.Executer == nil { + return false + } + + // compiled workflow not available + if len(template.Workflows) > 0 && template.CompiledWorkflow == nil { + return false + } + + // template ID mismatch + if template.Options.TemplateID != template.ID { + return false + } + + // executer exists but no requests or flow available + if template.Executer != nil { + // NOTE(dwisiswant0): This is a basic sanity check since we can't access + // private fields, but we can check requests tho + if template.Requests() == 0 && template.Options.Flow == "" { + return false + } + } + + if template.Options.Options == nil { + return false + } + + return true +} + var ( jsCompiler *compiler.Compiler jsCompilerOnce = sync.OnceFunc(func() { From 5be258f948eb8d108797be0529d4678711fc794d Mon Sep 17 00:00:00 2001 From: zy9ard3 <67743789+zy9ard3@users.noreply.github.com> Date: Mon, 25 Aug 2025 01:15:56 +0530 Subject: [PATCH 091/135] no changes custom template message should be INF not ERR --- pkg/external/customtemplates/github.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/external/customtemplates/github.go b/pkg/external/customtemplates/github.go index 1c550a740..338a4cb80 100644 --- a/pkg/external/customtemplates/github.go +++ b/pkg/external/customtemplates/github.go @@ -53,7 +53,11 @@ func (customTemplate *customTemplateGitHubRepo) Update(ctx context.Context) { } err := customTemplate.pullChanges(clonePath, customTemplate.githubToken) if err != nil { - gologger.Error().Msgf("%s", err) + if strings.Contains(err.Error(), "already up-to-date") { + gologger.Info().Msgf("%s", err) + } else { + gologger.Error().Msgf("%s", err) + } } else { gologger.Info().Msgf("Repo %s/%s successfully pulled the changes.\n", customTemplate.owner, customTemplate.reponame) } From 19247ae74b99c5871b62d7c465a63edb446ceba1 Mon Sep 17 00:00:00 2001 From: Tarun Koyalwar <45962551+tarunKoyalwar@users.noreply.github.com> Date: Mon, 25 Aug 2025 15:06:58 +0700 Subject: [PATCH 092/135] Path-Based Fuzzing SQL fix (#6400) * setup claude * migrate to using errkit * fix unused imports + lint errors * update settings.json * fix url encoding issue * fix lint error * fix the path fuzzing component * fix lint error --- .claude/settings.local.json | 35 +++++++ .gitignore | 2 + CLAUDE.md | 83 +++++++++++++++++ cmd/integration-test/http.go | 16 ++-- cmd/integration-test/loader.go | 2 +- cmd/integration-test/profile-loader.go | 6 +- cmd/integration-test/template-dir.go | 2 +- cmd/nuclei/main.go | 2 +- cmd/tmc/main.go | 44 ++++----- go.mod | 10 +- go.sum | 20 ++-- internal/pdcp/writer.go | 16 ++-- internal/runner/lazy.go | 4 +- internal/runner/proxy.go | 2 +- lib/config.go | 19 ++-- lib/multi.go | 4 +- lib/sdk.go | 18 ++-- pkg/authprovider/authx/dynamic.go | 6 +- pkg/authprovider/authx/file.go | 8 +- pkg/authprovider/file.go | 11 ++- pkg/catalog/config/nucleiconfig.go | 18 ++-- pkg/catalog/loader/ai_loader.go | 29 +++--- pkg/catalog/loader/loader.go | 2 +- pkg/external/customtemplates/azure_blob.go | 5 +- pkg/external/customtemplates/gitlab.go | 5 +- pkg/external/customtemplates/s3.go | 5 +- .../customtemplates/templates_provider.go | 16 +++- pkg/fuzz/component/path.go | 83 ++++++++++------- pkg/fuzz/component/path_test.go | 59 +++++++++++- pkg/fuzz/execute.go | 13 ++- pkg/input/formats/openapi/generator.go | 16 ++-- pkg/input/provider/interface.go | 8 +- pkg/installer/template.go | 33 +++---- pkg/installer/util.go | 2 +- pkg/js/devtools/tsgen/scrape.go | 6 +- pkg/js/global/scripts.go | 3 +- pkg/js/gojs/set.go | 7 +- pkg/js/libs/mssql/mssql.go | 6 +- pkg/js/libs/mysql/mysql.go | 8 +- pkg/js/libs/net/net.go | 4 +- pkg/js/libs/postgres/postgres.go | 4 +- pkg/js/libs/redis/redis.go | 8 +- pkg/js/libs/smb/smb.go | 6 +- pkg/js/libs/smb/smbghost.go | 2 +- pkg/js/libs/smtp/smtp.go | 2 +- pkg/js/libs/ssh/ssh.go | 8 +- pkg/protocols/code/code.go | 9 +- pkg/protocols/common/interactsh/const.go | 2 +- pkg/protocols/common/interactsh/interactsh.go | 8 +- pkg/protocols/common/protocolstate/file.go | 5 +- .../common/protocolstate/headless.go | 23 +++-- pkg/protocols/headless/engine/page.go | 2 +- pkg/protocols/headless/engine/page_actions.go | 26 +++--- pkg/protocols/http/build_request.go | 66 ++++++++----- pkg/protocols/http/raw/raw.go | 14 +-- pkg/protocols/http/signer/aws-sign.go | 2 +- pkg/protocols/http/utils.go | 5 +- pkg/protocols/javascript/js.go | 12 +-- pkg/protocols/network/network.go | 5 +- pkg/protocols/network/request.go | 2 +- pkg/protocols/ssl/ssl.go | 16 ++-- .../exporters/markdown/util/markdown_utils.go | 4 +- pkg/reporting/reporting.go | 26 +++--- pkg/templates/compile.go | 4 +- pkg/templates/parser.go | 9 +- pkg/templates/parser_error.go | 29 ++---- pkg/templates/parser_validate.go | 11 ++- pkg/templates/signer/default.go | 2 +- pkg/templates/signer/tmpl_signer.go | 4 +- pkg/templates/template_sign.go | 6 +- pkg/templates/templates.go | 15 ++- pkg/testutils/fuzzplayground/sqli_test.go | 92 +++++++++++++++++++ pkg/tmplexec/flow/flow_executor.go | 14 +-- pkg/tmplexec/flow/flow_internal.go | 3 +- pkg/types/types.go | 9 +- 75 files changed, 690 insertions(+), 403 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 CLAUDE.md create mode 100644 pkg/testutils/fuzzplayground/sqli_test.go diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 000000000..bcd49f4c6 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,35 @@ +{ + "permissions": { + "allow": [ + "Bash(find:*)", + "Bash(mkdir:*)", + "Bash(cp:*)", + "Bash(ls:*)", + "Bash(make:*)", + "Bash(go:*)", + "Bash(golangci-lint:*)", + "Bash(git merge:*)", + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(git push:*)", + "Bash(git pull:*)", + "Bash(git fetch:*)", + "Bash(git checkout:*)", + "WebFetch(*)", + "Write(*)", + "WebSearch(*)", + "MultiEdit(*)", + "Edit(*)", + "Bash(gh:*)", + "Bash(grep:*)", + "Bash(tree:*)", + "Bash(./nuclei:*)", + "WebFetch(domain:github.com)" + ], + "deny": [ + "Bash(make run:*)", + "Bash(./bin/nuclei:*)" + ], + "defaultMode": "acceptEdits" + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index f5153fe0f..8e4f9d93e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,8 @@ /scrapefunc /scrapefuncs /tsgen +/integration_tests/integration-test +/integration_tests/nuclei # Templates /*.yaml diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..ba6e226f6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,83 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Nuclei is a modern, high-performance vulnerability scanner built in Go that leverages YAML-based templates for customizable vulnerability detection. It supports multiple protocols (HTTP, DNS, TCP, SSL, WebSocket, WHOIS, JavaScript, Code) and is designed for zero false positives through real-world condition simulation. + +## Development Commands + +### Building and Testing +- `make build` - Build the main nuclei binary to ./bin/nuclei +- `make test` - Run unit tests with race detection +- `make integration` - Run integration tests (builds and runs test suite) +- `make functional` - Run functional tests +- `make vet` - Run go vet for code analysis +- `make tidy` - Clean up go modules + +### Validation and Linting +- `make template-validate` - Validate nuclei templates using the built binary +- `go fmt ./...` - Format Go code +- `go vet ./...` - Static analysis + +### Development Tools +- `make devtools-all` - Build all development tools (bindgen, tsgen, scrapefuncs) +- `make jsupdate-all` - Update JavaScript bindings and TypeScript definitions +- `make docs` - Generate documentation +- `make memogen` - Generate memoization code for JavaScript libraries + +### Testing Specific Components +- Run single test: `go test -v ./pkg/path/to/package -run TestName` +- Integration tests are in `integration_tests/` and can be run via `make integration` + +## Architecture Overview + +### Core Components +- **cmd/nuclei** - Main CLI entry point with flag parsing and configuration +- **internal/runner** - Core runner that orchestrates the entire scanning process +- **pkg/core** - Execution engine with work pools and template clustering +- **pkg/templates** - Template parsing, compilation, and management +- **pkg/protocols** - Protocol implementations (HTTP, DNS, Network, etc.) +- **pkg/operators** - Matching and extraction logic (matchers/extractors) +- **pkg/catalog** - Template discovery and loading from disk/remote sources + +### Protocol Architecture +Each protocol (HTTP, DNS, Network, etc.) implements: +- Request interface with Compile(), ExecuteWithResults(), Match(), Extract() methods +- Operators embedding for matching/extraction functionality +- Protocol-specific request building and execution logic + +### Template System +- Templates are YAML files defining vulnerability detection logic +- Compiled into executable requests with operators (matchers/extractors) +- Support for workflows (multi-step template execution) +- Template clustering optimizes identical requests across multiple templates + +### Key Execution Flow +1. Template loading and compilation via pkg/catalog/loader +2. Input provider setup for targets +3. Engine creation with work pools for concurrency +4. Template execution with result collection via operators +5. Output writing and reporting integration + +### JavaScript Integration +- Custom JavaScript runtime for code protocol templates +- Auto-generated bindings in pkg/js/generated/ +- Library implementations in pkg/js/libs/ +- Development tools for binding generation in pkg/js/devtools/ + +## Template Development +- Templates located in separate nuclei-templates repository +- YAML format with info, requests, and operators sections +- Support for multiple protocol types in single template +- Built-in DSL functions for dynamic content generation +- Template validation available via `make template-validate` + +## Key Directories +- **lib/** - SDK for embedding nuclei as a library +- **examples/** - Usage examples for different scenarios +- **integration_tests/** - Integration test suite with protocol-specific tests +- **pkg/fuzz/** - Fuzzing engine and DAST capabilities +- **pkg/input/** - Input processing for various formats (Burp, OpenAPI, etc.) +- **pkg/reporting/** - Result export and issue tracking integrations \ No newline at end of file diff --git a/cmd/integration-test/http.go b/cmd/integration-test/http.go index 69fb35187..8b587fffa 100644 --- a/cmd/integration-test/http.go +++ b/cmd/integration-test/http.go @@ -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 errkit.Wrap(routerErr, "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 = errkit.Append(errx, errkit.New("key1 not found in params", "expected", []string{"value1"}, "got", 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 = errkit.Append(errx, errkit.New("key2 not found in params", "expected", []string{"value2"}, "got", 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 = errkit.Append(errx, errkit.New("something not found in params", "expected", []string{"here"}, "got", 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 = errkit.Append(errx, errkit.New("key not found in params", "expected", []string{"value"}, "got", 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 errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.New("expected requests to be sent to `/one` and `/two` endpoints but were sent to `%v`", gotReqToEndpoints, "filePath", filePath) } return nil } diff --git a/cmd/integration-test/loader.go b/cmd/integration-test/loader.go index 2967e9afb..d6fc54644 100644 --- a/cmd/integration-test/loader.go +++ b/cmd/integration-test/loader.go @@ -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 errkit.Wrap(err, "failed to load template with id") } return expectResultsCount(results, 1) } diff --git a/cmd/integration-test/profile-loader.go b/cmd/integration-test/profile-loader.go index 19e57ba48..3cef723ab 100644 --- a/cmd/integration-test/profile-loader.go +++ b/cmd/integration-test/profile-loader.go @@ -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 errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.Wrap(err, "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)) diff --git a/cmd/integration-test/template-dir.go b/cmd/integration-test/template-dir.go index 96da87424..5f26a05aa 100644 --- a/cmd/integration-test/template-dir.go +++ b/cmd/integration-test/template-dir.go @@ -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 errkit.Wrap(err, "failed to create temp dir") } defer func() { _ = os.RemoveAll(tempdir) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index ba71a1e0f..0698fb96d 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -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 errkit.Wrap(err, "couldn't create crash resume file") } return nil }) diff --git a/cmd/tmc/main.go b/cmd/tmc/main.go index 69065436d..fa9bc8ea5 100644 --- a/cmd/tmc/main.go +++ b/cmd/tmc/main.go @@ -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, errkit.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, errkit.New(templateResp.ValidateError[0].Message+": at line %v", templateResp.ValidateError[0].Mark.Line, "tag", "validate") } - return data, false, errkit.New("validate: validation failed").Build() + return data, false, errkit.New("validation failed", "tag", "validate") } if templateResp.Error.Name != "" { - return data, false, errkit.New(templateResp.Error.Name).Build() + return data, false, errkit.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, errkit.New(templateResp.LintError.Reason+" : at line %v", templateResp.LintError.Mark.Line, "tag", "lint") } - return data, false, errkit.New(fmt.Sprintf("lint: at line: %v", templateResp.LintError.Mark.Line)).Build() + return data, false, errkit.New("at line: %v", templateResp.LintError.Mark.Line, "tag", "lint") } - return data, false, errkit.New("template enhance failed").Build() + return data, false, errkit.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, errkit.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, errkit.New(templateResp.ValidateError[0].Message+": at line %v", templateResp.ValidateError[0].Mark.Line, "tag", "validate") } - return data, false, errkit.New("validate: validation failed").Build() + return data, false, errkit.New("validation failed", "tag", "validate") } if templateResp.Error.Name != "" { - return data, false, errkit.New(templateResp.Error.Name).Build() + return data, false, errkit.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, errkit.New(templateResp.LintError.Reason+" : at line %v", templateResp.LintError.Mark.Line, "tag", "lint") } - return data, false, errkit.New(fmt.Sprintf("lint: at line: %v", templateResp.LintError.Mark.Line)).Build() + return data, false, errkit.New("at line: %v", templateResp.LintError.Mark.Line, "tag", "lint") } - return data, false, errkit.New("template format failed").Build() + return data, false, errkit.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, errkit.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, errkit.New(lintResp.LintError.Reason+" : at line %v", lintResp.LintError.Mark.Line, "tag", "lint") } - return false, errkit.New(fmt.Sprintf("lint: at line: %v", lintResp.LintError.Mark.Line)).Build() + return false, errkit.New("at line: %v", lintResp.LintError.Mark.Line, "tag", "lint") } // 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, errkit.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, errkit.New(validateResp.ValidateError[0].Message+": at line %v", validateResp.ValidateError[0].Mark.Line, "tag", "validate") } - return false, errkit.New("validate: validation failed").Build() + return false, errkit.New("validation failed", "tag", "validate") } if validateResp.Error.Name != "" { - return false, errkit.New(validateResp.Error.Name).Build() + return false, errkit.New("%s", validateResp.Error.Name) } - return false, errkit.New("template validation failed").Build() + return false, errkit.New("template validation failed") } // parseAndAddMaxRequests parses and adds max requests to templates diff --git a/go.mod b/go.mod index 2fd4ee3b5..191fd9b41 100644 --- a/go.mod +++ b/go.mod @@ -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/fastdialer v0.4.6 github.com/projectdiscovery/hmap v0.0.92 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/retryablehttp-go v1.0.120 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.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.20 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.24-0.20250823123502-bd7f2849ddb4 github.com/projectdiscovery/wappalyzergo v0.2.36 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 @@ -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.23.1 // 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 diff --git a/go.sum b/go.sum index 5fa540e33..3551fb73c 100644 --- a/go.sum +++ b/go.sum @@ -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.23.1 h1:8+EYZZcm9xObBgCIBb8f5sg65qVtphg7VcbMOjuvNrE= +github.com/gaissmai/bart v0.23.1/go.mod h1:RpLtt3lWq1BoRz3AAyDAJ7jhLWBkYhVCfi+ximB2t68= 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= @@ -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.6 h1:7cw47IyrkVHCEM80dBDhjT4YNsPY2IAZD2Sg11QM0Wk= +github.com/projectdiscovery/fastdialer v0.4.6/go.mod h1:IRbTB9d2GNT1EyxA16b/HJpqYbnNXk6hsH8CRZkdukc= 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= @@ -801,8 +801,8 @@ 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.20 h1:dPUk3FKoAehMnFvphAZLq6khDCbPYPJnD6PPTcjp5nU= +github.com/projectdiscovery/networkpolicy v0.1.20/go.mod h1:laPi8mLbgCbYZ0kYQU4fkWCFQdFbx24ci7yBQA8Hcww= 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= @@ -811,8 +811,8 @@ github.com/projectdiscovery/rdap v0.9.0 h1:wPhHx5pQ2QI+WGhyNb2PjhTl0NtB39Nk7YFZ9 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/retryablehttp-go v1.0.120 h1:kH4D0MwKV6a0U6YbBQ8cBD+tT0U3zrwudTPCFVSaZg8= +github.com/projectdiscovery/retryablehttp-go v1.0.120/go.mod h1:jR3eJLdCEvW3Xz0LOQldxNc+MHHY61qZh9k3Sz7U40U= 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.24-0.20250823123502-bd7f2849ddb4 h1:qQMEhfxDsiZ+Ay3dj93FuMAa7yt1XE2bxDpPSTEz/P0= +github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4/go.mod h1:ipzU2PHYP71MaMn4jllPOpdYpdMkFD0jE3Tjak4b4eM= 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= diff --git a/internal/pdcp/writer.go b/internal/pdcp/writer.go index ed98d556e..778d2ccc9 100644 --- a/internal/pdcp/writer.go +++ b/internal/pdcp/writer.go @@ -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, errkit.Wrap(err, "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, errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.Wrap(err, fmt.Sprintf("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, errkit.Wrap(err, "could not create cloud upload request") } // add pdtm meta params req.Params.Merge(updateutils.GetpdtmParams(config.Version)) diff --git a/internal/runner/lazy.go b/internal/runner/lazy.go index 27f223e6d..1202620fe 100644 --- a/internal/runner/lazy.go +++ b/internal/runner/lazy.go @@ -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, errkit.Wrap(err, "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, errkit.Wrap(err, "failed to initialize dynamic auth templates store") } return store, nil } diff --git a/internal/runner/proxy.go b/internal/runner/proxy.go index 4584eedcc..6ff3c43f7 100644 --- a/internal/runner/proxy.go +++ b/internal/runner/proxy.go @@ -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 errkit.Wrapf(err, "failed to parse proxy got %v", err) } if options.ProxyInternal { _ = os.Setenv(HTTP_PROXY_ENV, proxyURL.String()) diff --git a/lib/config.go b/lib/config.go index 24af8fdbf..2c2a585d9 100644 --- a/lib/config.go +++ b/lib/config.go @@ -8,6 +8,7 @@ import ( "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/ratelimit" + "github.com/projectdiscovery/utils/errkit" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" @@ -102,7 +103,7 @@ type InteractshOpts interactsh.Options func WithInteractshOptions(opts InteractshOpts) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported("WithInteractshOptions") + return errkit.Wrap(ErrOptionsNotSupported, "WithInteractshOptions") } optsPtr := &opts e.interactshOpts = (*interactsh.Options)(optsPtr) @@ -229,7 +230,7 @@ type StatsOptions struct { func EnableStatsWithOpts(opts StatsOptions) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported("EnableStatsWithOpts") + return errkit.Wrap(ErrOptionsNotSupported, "EnableStatsWithOpts") } if opts.Interval == 0 { opts.Interval = 5 //sec @@ -257,7 +258,7 @@ type VerbosityOptions struct { func WithVerbosity(opts VerbosityOptions) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported("WithVerbosity") + return errkit.Wrap(ErrOptionsNotSupported, "WithVerbosity") } e.opts.Verbose = opts.Verbose e.opts.Silent = opts.Silent @@ -290,7 +291,7 @@ type NetworkConfig struct { func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported("WithNetworkConfig") + return errkit.Wrap(ErrOptionsNotSupported, "WithNetworkConfig") } e.opts.NoHostErrors = opts.DisableMaxHostErr e.opts.MaxHostError = opts.MaxHostError @@ -321,7 +322,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 errkit.Wrap(ErrOptionsNotSupported, "WithProxy") } e.opts.Proxy = proxy e.opts.ProxyInternal = proxyInternalRequests @@ -346,7 +347,7 @@ type OutputWriter output.Writer func UseOutputWriter(writer OutputWriter) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported("UseOutputWriter") + return errkit.Wrap(ErrOptionsNotSupported, "UseOutputWriter") } e.customWriter = writer return nil @@ -361,7 +362,7 @@ type StatsWriter progress.Progress func UseStatsWriter(writer StatsWriter) NucleiSDKOptions { return func(e *NucleiEngine) error { if e.mode == threadSafe { - return ErrOptionsNotSupported("UseStatsWriter") + return errkit.Wrap(ErrOptionsNotSupported, "UseStatsWriter") } e.customProgress = writer return nil @@ -375,7 +376,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 errkit.Wrap(ErrOptionsNotSupported, "WithTemplateUpdateCallback") } e.disableTemplatesAutoUpgrade = disableTemplatesAutoUpgrade e.onUpdateAvailableCallback = callback @@ -387,7 +388,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 errkit.Wrap(ErrOptionsNotSupported, "WithSandboxOptions") } e.opts.AllowLocalFileAccess = allowLocalFileAccess e.opts.RestrictLocalNetworkAccess = restrictLocalNetworkAccess diff --git a/lib/multi.go b/lib/multi.go index d224d09f6..5c542513c 100644 --- a/lib/multi.go +++ b/lib/multi.go @@ -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 errkit.Wrapf(err, "Could not create workflow loader: %s", 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 errkit.Wrapf(err, "Could not create loader client: %s", err) } store.Load() diff --git a/lib/sdk.go b/lib/sdk.go index 76fc8870b..3ed252178 100644 --- a/lib/sdk.go +++ b/lib/sdk.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "context" - "fmt" "io" "sync" @@ -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 = errkit.New("Not implemented") // ErrNoTemplatesAvailable is returned when no templates are available to execute - ErrNoTemplatesAvailable = errkit.New("No templates available").Build() + ErrNoTemplatesAvailable = errkit.New("No templates available") // ErrNoTargetsAvailable is returned when no targets are available to scan - ErrNoTargetsAvailable = errkit.New("No targets available").Build() + ErrNoTargetsAvailable = errkit.New("No targets available") + // ErrOptionsNotSupported is returned when an option is not supported in thread safe mode + ErrOptionsNotSupported = errkit.New("Option 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 errkit.Wrapf(err, "Could not create workflow loader: %s", 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 errkit.Wrapf(err, "Could not create loader client: %s", err) } e.store.Load() e.templatesLoaded = true diff --git a/pkg/authprovider/authx/dynamic.go b/pkg/authprovider/authx/dynamic.go index 9a2427555..cff03147d 100644 --- a/pkg/authprovider/authx/dynamic.go +++ b/pkg/authprovider/authx/dynamic.go @@ -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 errkit.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 errkit.New(" template-path is required for dynamic secret") } if len(d.Variables) == 0 { - return errkit.New("variables are required for dynamic secret").Build() + return errkit.New("variables are required for dynamic secret") } if d.Secret != nil { diff --git a/pkg/authprovider/authx/file.go b/pkg/authprovider/authx/file.go index fc749fda3..804b6c340 100644 --- a/pkg/authprovider/authx/file.go +++ b/pkg/authprovider/authx/file.go @@ -237,7 +237,9 @@ 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) + errorErr := errkit.FromError(err) + errorErr.Msgf("could not unmarshal yaml") + return nil, errorErr } return &auth, nil } @@ -247,7 +249,9 @@ 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) + errorErr := errkit.FromError(err) + errorErr.Msgf("could not unmarshal json") + return nil, errorErr } return &auth, nil } diff --git a/pkg/authprovider/file.go b/pkg/authprovider/file.go index 02df46b6f..40f401906 100644 --- a/pkg/authprovider/file.go +++ b/pkg/authprovider/file.go @@ -1,7 +1,6 @@ package authprovider import ( - "fmt" "net" "net/url" "regexp" @@ -31,16 +30,20 @@ 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, errkit.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) + errorErr := errkit.FromError(err) + errorErr.Msgf("invalid secret in file: %s", path) + return nil, errorErr } } 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) + errorErr := errkit.FromError(err) + errorErr.Msgf("invalid dynamic in file: %s", path) + return nil, errorErr } dynamic.SetLazyFetchCallback(callback) store.Dynamic[i] = dynamic diff --git a/pkg/catalog/config/nucleiconfig.go b/pkg/catalog/config/nucleiconfig.go index 8496b69b3..e62dd37f4 100644 --- a/pkg/catalog/config/nucleiconfig.go +++ b/pkg/catalog/config/nucleiconfig.go @@ -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 errkit.Newf("could not read nuclei ignore file: %v", err) } 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 errkit.New("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 errkit.Newf("could not write nuclei config file at %s: %v", c.getTemplatesConfigFilePath(), err) } 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 errkit.Newf("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 errkit.Newf("could not read nuclei config file at %s: %v", c.getTemplatesConfigFilePath(), err) } 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 errkit.Newf("could not unmarshal nuclei config file at %s: %v", c.getTemplatesConfigFilePath(), err) } // 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 errkit.Newf("failed to marshal nuclei config: %v", err) } 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 errkit.Newf("failed to write nuclei config file at %s: %v", c.getTemplatesConfigFilePath(), err) } 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 errkit.Newf("could not create nuclei config directory at %s: %v", c.configDir, err) } } return nil diff --git a/pkg/catalog/loader/ai_loader.go b/pkg/catalog/loader/ai_loader.go index 5b30c4973..89e859cea 100644 --- a/pkg/catalog/loader/ai_loader.go +++ b/pkg/catalog/loader/ai_loader.go @@ -3,7 +3,6 @@ package loader import ( "bytes" "encoding/json" - "fmt" "io" "net/http" "os" @@ -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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("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 "", "", errkit.Newf("Failed to decode API response: %v", err) } if result.TemplateID == "" || result.Completion == "" { - return "", "", errkit.New("Failed to generate template").Build() + return "", "", errkit.Newf("Failed to generate template") } return result.Completion, result.TemplateID, nil diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 069e99b50..cfaf4e832 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -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, errkit.Wrapf(err, "Could not load template %s: got %v", uri, remoteTemplates) } resp, err := retryablehttp.Get(remoteTemplates[0]) if err != nil { diff --git a/pkg/external/customtemplates/azure_blob.go b/pkg/external/customtemplates/azure_blob.go index 180c45d8e..4dc935a9c 100644 --- a/pkg/external/customtemplates/azure_blob.go +++ b/pkg/external/customtemplates/azure_blob.go @@ -3,7 +3,6 @@ package customtemplates import ( "bytes" "context" - "fmt" "os" "path/filepath" "strings" @@ -30,7 +29,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("Error establishing Azure Blob client for %s", options.AzureContainerName) + return nil, errx } // Create a new Azure Blob Storage container object diff --git a/pkg/external/customtemplates/gitlab.go b/pkg/external/customtemplates/gitlab.go index fce4caa2d..9a0836e14 100644 --- a/pkg/external/customtemplates/gitlab.go +++ b/pkg/external/customtemplates/gitlab.go @@ -3,7 +3,6 @@ package customtemplates import ( "context" "encoding/base64" - "fmt" "os" "path/filepath" @@ -29,7 +28,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("Error establishing GitLab client for %s %s", options.GitLabServerURL, err) + return nil, errx } // Create a new GitLab service client diff --git a/pkg/external/customtemplates/s3.go b/pkg/external/customtemplates/s3.go index 8b4eabff9..8eb73c09c 100644 --- a/pkg/external/customtemplates/s3.go +++ b/pkg/external/customtemplates/s3.go @@ -2,7 +2,6 @@ package customtemplates import ( "context" - "fmt" "os" "path/filepath" "strings" @@ -65,7 +64,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("error downloading s3 bucket %s", options.AwsBucketName) + return nil, errx } ctBucket := &customTemplateS3Bucket{ bucketName: options.AwsBucketName, diff --git a/pkg/external/customtemplates/templates_provider.go b/pkg/external/customtemplates/templates_provider.go index a4691d5bf..b40a7d938 100644 --- a/pkg/external/customtemplates/templates_provider.go +++ b/pkg/external/customtemplates/templates_provider.go @@ -38,7 +38,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("could not create github providers for custom templates") + return nil, errx } for _, v := range githubProviders { ctm.providers = append(ctm.providers, v) @@ -47,7 +49,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("could not create s3 providers for custom templates") + return nil, errx } for _, v := range s3Providers { ctm.providers = append(ctm.providers, v) @@ -56,7 +60,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("could not create azure providers for custom templates") + return nil, errx } for _, v := range azureProviders { ctm.providers = append(ctm.providers, v) @@ -65,7 +71,9 @@ 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) + errx := errkit.FromError(err) + errx.Msgf("could not create gitlab providers for custom templates") + return nil, errx } for _, v := range gitlabProviders { ctm.providers = append(ctm.providers, v) diff --git a/pkg/fuzz/component/path.go b/pkg/fuzz/component/path.go index e77429c19..c3f450a76 100644 --- a/pkg/fuzz/component/path.go +++ b/pkg/fuzz/component/path.go @@ -7,7 +7,6 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/fuzz/dataformat" "github.com/projectdiscovery/retryablehttp-go" - mapsutil "github.com/projectdiscovery/utils/maps" urlutil "github.com/projectdiscovery/utils/url" ) @@ -38,12 +37,18 @@ func (q *Path) Parse(req *retryablehttp.Request) (bool, error) { splitted := strings.Split(req.Path, "/") values := make(map[string]interface{}) - for i := range splitted { - pathTillNow := strings.Join(splitted[:i+1], "/") - if pathTillNow == "" { + for i, segment := range splitted { + if segment == "" && i == 0 { + // Skip the first empty segment from leading "/" continue } - values[strconv.Itoa(i)] = pathTillNow + if segment == "" { + // Skip any other empty segments + continue + } + // Use 1-based indexing and store individual segments + key := strconv.Itoa(len(values) + 1) + values[key] = segment } q.value.SetParsed(dataformat.KVMap(values), "") return true, nil @@ -64,7 +69,7 @@ func (q *Path) Iterate(callback func(key string, value interface{}) error) (err // SetValue sets a value in the component // for a key func (q *Path) SetValue(key string, value string) error { - escaped := urlutil.ParamEncode(value) + escaped := urlutil.PathEncode(value) if !q.value.SetParsedValue(key, escaped) { return ErrSetValue } @@ -82,40 +87,48 @@ func (q *Path) Delete(key string) error { // Rebuild returns a new request with the // component rebuilt func (q *Path) Rebuild() (*retryablehttp.Request, error) { - originalValues := mapsutil.Map[string, any]{} - splitted := strings.Split(q.req.Path, "/") - for i := range splitted { - pathTillNow := strings.Join(splitted[:i+1], "/") - if pathTillNow == "" { - continue - } - originalValues[strconv.Itoa(i)] = pathTillNow + // Get the original path segments + originalSplitted := strings.Split(q.req.Path, "/") + + // Create a new slice to hold the rebuilt segments + rebuiltSegments := make([]string, 0, len(originalSplitted)) + + // Add the first empty segment (from leading "/") + if len(originalSplitted) > 0 && originalSplitted[0] == "" { + rebuiltSegments = append(rebuiltSegments, "") } - - originalPath := q.req.Path - lengthSplitted := len(q.value.parsed.Map) - for i := lengthSplitted; i > 0; i-- { - key := strconv.Itoa(i) - - original, ok := originalValues.GetOrDefault(key, "").(string) - if !ok { + + // Process each segment + segmentIndex := 1 // 1-based indexing for our stored values + for i := 1; i < len(originalSplitted); i++ { + originalSegment := originalSplitted[i] + if originalSegment == "" { + // Skip empty segments continue } - - new, ok := q.value.parsed.Map.GetOrDefault(key, "").(string) - if !ok { - continue + + // Check if we have a replacement for this segment + key := strconv.Itoa(segmentIndex) + if newValue, exists := q.value.parsed.Map.GetOrDefault(key, "").(string); exists && newValue != "" { + rebuiltSegments = append(rebuiltSegments, newValue) + } else { + rebuiltSegments = append(rebuiltSegments, originalSegment) } - - if new == original { - // no need to replace - continue - } - - originalPath = strings.Replace(originalPath, original, new, 1) + segmentIndex++ + } + + // Join the segments back into a path + rebuiltPath := strings.Join(rebuiltSegments, "/") + + if unescaped, err := urlutil.PathDecode(rebuiltPath); err == nil { + // this is handle the case where anyportion of path has url encoded data + // by default the http/request official library will escape/encode special characters in path + // to avoid double encoding we unescape/decode already encoded value + // + // if there is a invalid url encoded value like %99 then it will still be encoded as %2599 and not %99 + // the only way to make sure it stays as %99 is to implement raw request and unsafe for fuzzing as well + rebuiltPath = unescaped } - - rebuiltPath := originalPath // Clone the request and update the path cloned := q.req.Clone(context.Background()) diff --git a/pkg/fuzz/component/path_test.go b/pkg/fuzz/component/path_test.go index bf1f2f2aa..5772c953d 100644 --- a/pkg/fuzz/component/path_test.go +++ b/pkg/fuzz/component/path_test.go @@ -29,9 +29,9 @@ func TestURLComponent(t *testing.T) { }) require.Equal(t, []string{"1"}, keys, "unexpected keys") - require.Equal(t, []string{"/testpath"}, values, "unexpected values") + require.Equal(t, []string{"testpath"}, values, "unexpected values") - err = urlComponent.SetValue("1", "/newpath") + err = urlComponent.SetValue("1", "newpath") if err != nil { t.Fatal(err) } @@ -61,9 +61,10 @@ func TestURLComponent_NestedPaths(t *testing.T) { isSet := false _ = path.Iterate(func(key string, value interface{}) error { - if !isSet && value.(string) == "/user/753" { + t.Logf("Key: %s, Value: %s", key, value.(string)) + if !isSet && value.(string) == "753" { isSet = true - if setErr := path.SetValue(key, "/user/753'"); setErr != nil { + if setErr := path.SetValue(key, "753'"); setErr != nil { t.Fatal(setErr) } } @@ -75,6 +76,54 @@ func TestURLComponent_NestedPaths(t *testing.T) { t.Fatal(err) } if newReq.Path != "/user/753'/profile" { - t.Fatal("expected path to be modified") + t.Fatalf("expected path to be '/user/753'/profile', got '%s'", newReq.Path) } } + +func TestPathComponent_SQLInjection(t *testing.T) { + path := NewPath() + req, err := retryablehttp.NewRequest(http.MethodGet, "https://example.com/user/55/profile", nil) + if err != nil { + t.Fatal(err) + } + found, err := path.Parse(req) + if err != nil { + t.Fatal(err) + } + if !found { + t.Fatal("expected path to be found") + } + + t.Logf("Original path: %s", req.Path) + + // Let's see what path segments are available for fuzzing + err = path.Iterate(func(key string, value interface{}) error { + t.Logf("Key: %s, Value: %s", key, value.(string)) + + // Try fuzzing the "55" segment specifically (which should be key "2") + if value.(string) == "55" { + if setErr := path.SetValue(key, "55 OR True"); setErr != nil { + t.Fatal(setErr) + } + } + return nil + }) + if err != nil { + t.Fatal(err) + } + + newReq, err := path.Rebuild() + if err != nil { + t.Fatal(err) + } + + t.Logf("Modified path: %s", newReq.Path) + + // Now with PathEncode, spaces are preserved correctly for SQL injection + if newReq.Path != "/user/55 OR True/profile" { + t.Fatalf("expected path to be '/user/55 OR True/profile', got '%s'", newReq.Path) + } + + // Let's also test what the actual URL looks like + t.Logf("Full URL: %s", newReq.String()) +} diff --git a/pkg/fuzz/execute.go b/pkg/fuzz/execute.go index ddec76505..3cd2e3645 100644 --- a/pkg/fuzz/execute.go +++ b/pkg/fuzz/execute.go @@ -23,10 +23,9 @@ import ( 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 = errkit.New("rule not applicable") +) // IsErrRuleNotApplicable checks if an error is due to rule not applicable func IsErrRuleNotApplicable(err error) bool { @@ -90,10 +89,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 errkit.Newf("rule not applicable: 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 errkit.Newf("rule not applicable: both base request and reqresp are nil for %v", input.Input.MetaInput.Input) } var finalComponentList []component.Component @@ -145,7 +144,7 @@ func (rule *Rule) Execute(input *ExecuteRuleInput) (err error) { } if len(finalComponentList) == 0 { - return ErrRuleNotApplicable("no component matched on this rule") + return errkit.Newf("rule not applicable: no component matched on this rule") } baseValues := input.Values diff --git a/pkg/input/formats/openapi/generator.go b/pkg/input/formats/openapi/generator.go index 3d758cbc9..436286256 100644 --- a/pkg/input/formats/openapi/generator.go +++ b/pkg/input/formats/openapi/generator.go @@ -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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("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, errkit.Newf("unsupported security scheme type (%s) found in openapi file", scheme.Value.Type) } diff --git a/pkg/input/provider/interface.go b/pkg/input/provider/interface.go index c93a329de..32b923dd6 100644 --- a/pkg/input/provider/interface.go +++ b/pkg/input/provider/interface.go @@ -18,14 +18,10 @@ import ( ) var ( - ErrInactiveInput = fmt.Errorf("input is inactive") + ErrNotImplemented = errkit.New("provider does not implement method") + 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" diff --git a/pkg/installer/template.go b/pkg/installer/template.go index 62fefb0a6..577f8c252 100644 --- a/pkg/installer/template.go +++ b/pkg/installer/template.go @@ -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 errkit.Wrapf(err, "failed to install templates at %s", config.DefaultConfig.TemplatesDirectory) } if t.CustomTemplates != nil { t.CustomTemplates.Download(context.TODO()) @@ -121,7 +121,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 errkit.Wrapf(err, "failed to create directory at %s", dir) } } if t.DisablePublicTemplates { @@ -130,12 +130,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 errkit.Wrapf(err, "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 errkit.Wrapf(err, "failed to write templates to disk at %s", dir) } gologger.Info().Msgf("Successfully installed nuclei-templates at %s", dir) return nil @@ -156,7 +156,7 @@ 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 errkit.Wrapf(err, "failed to install templates at %s", dir) } latestVersion := ghrd.Latest.GetTagName() @@ -177,7 +177,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 errkit.Wrapf(err, "failed to get checksums from %s after update", dir) } // summarize all changes @@ -299,7 +299,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 errkit.Wrapf(err, "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 +310,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 errkit.Wrapf(err, "failed to write file %s", uri) } // after successful write, remove old template if err := os.Remove(oldPath); err != nil { @@ -325,20 +325,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 errkit.Wrap(err, "failed to download templates") } if err := config.DefaultConfig.WriteTemplatesConfig(); err != nil { - return errkit.Append(errkit.New("failed to write templates config"), err) + return errkit.Wrap(err, "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 errkit.Wrap(err, "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 errkit.Wrap(err, "failed to update templates version") } PurgeEmptyDirectories(dir) @@ -348,11 +348,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 errkit.Wrap(err, "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 errkit.Wrap(err, "failed to write nuclei templates index") } if !HideReleaseNotes { @@ -448,8 +448,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, errkit.Wrap(err, "failed to calculate checksums of templates") } diff --git a/pkg/installer/util.go b/pkg/installer/util.go index a0bc99751..c0ba27f96 100644 --- a/pkg/installer/util.go +++ b/pkg/installer/util.go @@ -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, errkit.New("version not found") } data, err := io.ReadAll(resp.Body) if err != nil { diff --git a/pkg/js/devtools/tsgen/scrape.go b/pkg/js/devtools/tsgen/scrape.go index 3c846ad7d..aac352dfc 100644 --- a/pkg/js/devtools/tsgen/scrape.go +++ b/pkg/js/devtools/tsgen/scrape.go @@ -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 errkit.Newf("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 errkit.Newf("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 errkit.Newf("%v is not a type name", typeName) } // Ensure the type is a named struct type namedStruct, ok := typeNameObj.Type().Underlying().(*types.Struct) diff --git a/pkg/js/global/scripts.go b/pkg/js/global/scripts.go index 5bd625cbc..4336edf61 100644 --- a/pkg/js/global/scripts.go +++ b/pkg/js/global/scripts.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "embed" - "fmt" "math/rand" "net" "reflect" @@ -257,7 +256,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 errkit.Wrapf(err, "could not import default modules %v", defaultImports) } return nil diff --git a/pkg/js/gojs/set.go b/pkg/js/gojs/set.go index 72aece402..4d4407def 100644 --- a/pkg/js/gojs/set.go +++ b/pkg/js/gojs/set.go @@ -2,7 +2,6 @@ package gojs import ( "context" - "fmt" "reflect" "github.com/Mzack9999/goja" @@ -10,8 +9,8 @@ import ( ) var ( - ErrInvalidFuncOpts = errkit.New("invalid function options: %v").Build() - ErrNilRuntime = errkit.New("runtime is nil").Build() + ErrInvalidFuncOpts = errkit.New("invalid function options") + ErrNilRuntime = errkit.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 errkit.Newf("invalid function options: name: %s, signatures: %v, description: %s", opts.Name, opts.Signatures, opts.Description) } // Wrap the function with context injection diff --git a/pkg/js/libs/mssql/mssql.go b/pkg/js/libs/mssql/mssql.go index f1a538db2..4f9caf275 100644 --- a/pkg/js/libs/mssql/mssql.go +++ b/pkg/js/libs/mssql/mssql.go @@ -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)) diff --git a/pkg/js/libs/mysql/mysql.go b/pkg/js/libs/mysql/mysql.go index a059766d3..c48c73a83 100644 --- a/pkg/js/libs/mysql/mysql.go +++ b/pkg/js/libs/mysql/mysql.go @@ -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 diff --git a/pkg/js/libs/net/net.go b/pkg/js/libs/net/net.go index 2f486bfa5..ad1eaadd3 100644 --- a/pkg/js/libs/net/net.go +++ b/pkg/js/libs/net/net.go @@ -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{}, errkit.Wrapf(err, "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{}, errkit.Wrapf(err, "failed to read %d bytes", N) } return b[:n], nil } diff --git a/pkg/js/libs/postgres/postgres.go b/pkg/js/libs/postgres/postgres.go index 4dd1cd542..322048a8b 100644 --- a/pkg/js/libs/postgres/postgres.go +++ b/pkg/js/libs/postgres/postgres.go @@ -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)) diff --git a/pkg/js/libs/redis/redis.go b/pkg/js/libs/redis/redis.go index 501788243..84b96d86b 100644 --- a/pkg/js/libs/redis/redis.go +++ b/pkg/js/libs/redis/redis.go @@ -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{ diff --git a/pkg/js/libs/smb/smb.go b/pkg/js/libs/smb/smb.go index 62a804609..7dc2dc83b 100644 --- a/pkg/js/libs/smb/smb.go +++ b/pkg/js/libs/smb/smb.go @@ -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 { diff --git a/pkg/js/libs/smb/smbghost.go b/pkg/js/libs/smb/smbghost.go index bf498f3ba..69ddcca1e 100644 --- a/pkg/js/libs/smb/smbghost.go +++ b/pkg/js/libs/smb/smbghost.go @@ -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) diff --git a/pkg/js/libs/smtp/smtp.go b/pkg/js/libs/smtp/smtp.go index f0f4b90b1..d4a7e0227 100644 --- a/pkg/js/libs/smtp/smtp.go +++ b/pkg/js/libs/smtp/smtp.go @@ -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) diff --git a/pkg/js/libs/ssh/ssh.go b/pkg/js/libs/ssh/ssh.go index ebb041e20..028bd7881 100644 --- a/pkg/js/libs/ssh/ssh.go +++ b/pkg/js/libs/ssh/ssh.go @@ -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 "", errkit.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 errkit.New("host is required") } if c.Port <= 0 { - return errkit.New("port is required").Build() + return errkit.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 diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index 0a17c9f3f..92d951ba6 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -11,7 +11,6 @@ import ( "github.com/Mzack9999/goja" "github.com/alecthomas/chroma/quick" "github.com/ditashi/jsbeautifier-go/jsbeautifier" - "github.com/pkg/errors" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/gozero" @@ -113,7 +112,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 errkit.Wrap(err, errMsg) } } else { request.gozero = engine @@ -132,7 +131,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { compiled.ExcludeMatchers = options.ExcludeMatchers compiled.TemplateID = options.TemplateID if err := compiled.Compile(); err != nil { - return errors.Wrap(err, "could not compile operators") + return errkit.Wrap(err, "could not compile operators") } for _, matcher := range compiled.Matchers { // default matcher part for code protocol is response @@ -153,7 +152,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 errkit.Newf("could not compile pre-condition: %s", err) } request.preConditionCompiled = preConditionCompiled } @@ -230,7 +229,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 errkit.Newf("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) diff --git a/pkg/protocols/common/interactsh/const.go b/pkg/protocols/common/interactsh/const.go index aad130d46..46e5c2687 100644 --- a/pkg/protocols/common/interactsh/const.go +++ b/pkg/protocols/common/interactsh/const.go @@ -8,7 +8,7 @@ import ( var ( defaultInteractionDuration = 60 * time.Second - interactshURLMarkerRegex = regexp.MustCompile(`(%7[B|b]|\{){2}(interactsh-url(?:_[0-9]+){0,3})(%7[D|d]|\}){2}`) + interactshURLMarkerRegex = regexp.MustCompile(`(%7[B|b]|\{){2}(interactsh-url(?:_[0-9]+){0,3})(%7[D|d]|\}){2}`) ErrInteractshClientNotInitialized = errors.New("interactsh client not initialized") ) diff --git a/pkg/protocols/common/interactsh/interactsh.go b/pkg/protocols/common/interactsh/interactsh.go index 6cf7b1228..7cdf7c77b 100644 --- a/pkg/protocols/common/interactsh/interactsh.go +++ b/pkg/protocols/common/interactsh/interactsh.go @@ -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 errkit.Wrap(err, "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 errkit.Is(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 errkit.Wrap(err, "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 "", errkit.Wrap(ErrInteractshClientNotInitialized, err.Error()) } if c.interactsh == nil { diff --git a/pkg/protocols/common/protocolstate/file.go b/pkg/protocols/common/protocolstate/file.go index 0ca4dd3b7..4957fa68d 100644 --- a/pkg/protocols/common/protocolstate/file.go +++ b/pkg/protocols/common/protocolstate/file.go @@ -1,7 +1,6 @@ package protocolstate import ( - "fmt" "strings" "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" @@ -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 "", errkit.Wrapf(err, "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 "", errkit.Newf("path %v is outside nuclei-template directory and -lfa is not enabled", filePath) } diff --git a/pkg/protocols/common/protocolstate/headless.go b/pkg/protocols/common/protocolstate/headless.go index ee75c3b31..8b593a96c 100644 --- a/pkg/protocols/common/protocolstate/headless.go +++ b/pkg/protocols/common/protocolstate/headless.go @@ -2,7 +2,6 @@ package protocolstate import ( "context" - "fmt" "net" "strings" @@ -18,14 +17,18 @@ 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() +var ( + ErrURLDenied = errkit.New("headless: url dropped by rule") + ErrHostDenied = errorTemplate{format: "host %v dropped by network policy"} +) + +// errorTemplate provides a way to create formatted errors like the old errorutil.NewWithFmt +type errorTemplate struct { + format string } -// 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() +func (e errorTemplate) Msgf(args ...interface{}) error { + return errkit.Newf(e.format, args...) } func GetNetworkPolicy(ctx context.Context) *networkpolicy.NetworkPolicy { @@ -47,15 +50,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), errkit.Newf("headless: url %v dropped by rule: %v", 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), errkit.Newf("headless: url %v dropped by rule: %v", 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), errkit.Newf("headless: url %v dropped by rule: %v", reqURL, "address blocked by network policy")) } return nil } diff --git a/pkg/protocols/headless/engine/page.go b/pkg/protocols/headless/engine/page.go index 86f95a0e8..6b518dd38 100644 --- a/pkg/protocols/headless/engine/page.go +++ b/pkg/protocols/headless/engine/page.go @@ -78,7 +78,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, errkit.Wrapf(err, "could not parse URL %s", target) } hasTrailingSlash := httputil.HasTrailingSlash(target) diff --git a/pkg/protocols/headless/engine/page_actions.go b/pkg/protocols/headless/engine/page_actions.go index 1a11bdc7f..475480464 100644 --- a/pkg/protocols/headless/engine/page_actions.go +++ b/pkg/protocols/headless/engine/page_actions.go @@ -31,8 +31,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 = errkit.New("invalid arguments provided") + ErrLFAccessDenied = errkit.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 +59,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 = errkit.Newf("panic on headless action: %v", r) } }() @@ -72,7 +72,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, errkit.Wrap(err, "error occurred while executing waitFunc") } } } @@ -400,7 +400,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 errkit.Newf("failed to parse url %v while creating http request", url) } // ===== parameter automerge ===== @@ -410,7 +410,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 errkit.Wrapf(err, "could not navigate to url %s", parsedURL.String()) } p.updateLastNavigatedURL() @@ -524,14 +524,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 errkit.Newf("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 errkit.Wrap(err, "could not get current working directory") } if !strings.HasPrefix(to, cwd) { @@ -550,7 +550,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 errkit.Wrap(err, "failed to create directory while writing screenshot") } } @@ -562,7 +562,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 errkit.Newf("failed to write screenshot, file %v already exists", filePath) } err = os.WriteFile(filePath, data, 0540) if err != nil { @@ -805,12 +805,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, errkit.Newf("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, errkit.Newf("event %q is not a page event", event) } waitEvent = tmp @@ -947,7 +947,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 "", errkit.Wrapf(err, "argument %q, value: %q", arg, argValue) } argValue, err = expressions.Evaluate(argValue, p.variables) diff --git a/pkg/protocols/http/build_request.go b/pkg/protocols/http/build_request.go index 7dac41568..0fa8d1502 100644 --- a/pkg/protocols/http/build_request.go +++ b/pkg/protocols/http/build_request.go @@ -37,18 +37,42 @@ 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) - } +// ErrEvalExpression +type errorTemplate struct { + format string } -// 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() +func (e errorTemplate) Wrap(err error) wrapperError { + return wrapperError{template: e, err: err} } +func (e errorTemplate) Msgf(args ...interface{}) error { + return errkit.Newf(e.format, args...) +} + +type wrapperError struct { + template errorTemplate + err error +} + +func (w wrapperError) WithTag(tag string) error { + return errkit.Wrap(w.err, w.template.format) +} + +func (w wrapperError) Msgf(format string, args ...interface{}) error { + return errkit.Wrapf(w.err, format, args...) +} + +func (w wrapperError) Error() string { + return errkit.Wrap(w.err, w.template.format).Error() +} + +// ErrEvalExpression +var ( + ErrEvalExpression = errorTemplate{"could not evaluate helper expressions"} + ErrUnresolvedVars = errorTemplate{"unresolved variables `%v` found in request"} +) + // generatedRequest is a single generated request wrapped for a template request type generatedRequest struct { original *Request @@ -199,7 +223,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, errkit.Wrap(err, "could not evaluate helper expressions") } } // finalVars contains allVars and any generator/fuzzing specific payloads @@ -216,7 +240,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, errkit.Wrap(err, "could not evaluate helper expressions") } if isRawRequest { @@ -225,7 +249,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, errkit.Newf("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 +282,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, errkit.Wrap(err, "could not evaluate helper expressions") } // If the request is a raw request, get the URL from the request // header and use it to make the request. @@ -281,7 +305,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, errkit.Newf("unresolved variables `%v` found in request", parts[1]) } parsed, err := urlutil.ParseURL(parts[1], true) @@ -295,19 +319,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, errkit.Wrap(err, "could not evaluate helper expressions") } 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, errkit.Newf("unresolved variables `%v` found in request", 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, errkit.Wrapf(err, "failed to parse %v in self contained request", data) } return r.generateHttpRequest(ctx, urlx, values, payloads) } @@ -318,7 +342,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, errkit.Wrap(err, "failed to evaluate while generating http request") } // Build a request on the specified URL req, err := retryablehttp.NewRequestFromURLWithContext(ctx, method, urlx, nil) @@ -347,7 +371,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, errkit.Wrap(err, "failed to parse raw request") } // Unsafe option uses rawhttp library @@ -363,7 +387,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, errkit.Wrapf(err, "failed to create request with url %v got %v", rawRequestData.FullURL, err) } req, err := retryablehttp.NewRequestFromURLWithContext(ctx, rawRequestData.Method, urlx, rawRequestData.Data) if err != nil { @@ -420,7 +444,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, errkit.Wrap(err, "failed to evaluate while adding headers to request") } req.Header[header] = []string{value} if header == "Host" { @@ -441,7 +465,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, errkit.Wrap(err, "could not evaluate helper expressions") } bodyReader, err := readerutil.NewReusableReadCloser([]byte(body)) if err != nil { diff --git a/pkg/protocols/http/raw/raw.go b/pkg/protocols/http/raw/raw.go index 11454bb77..c2a2121b6 100644 --- a/pkg/protocols/http/raw/raw.go +++ b/pkg/protocols/http/raw/raw.go @@ -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, errkit.Wrapf(err, "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, errkit.Wrapf(parseErr, "could not automergepath for template path %v", urlx.GetRelativePath()) } 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, errkit.Wrapf(err, "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, errkit.Wrapf(parseErr, "could not automergepath for template path %v", rawrequest.Path) } 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, errkit.Wrapf(err, "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, errkit.New("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, errkit.New("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) diff --git a/pkg/protocols/http/signer/aws-sign.go b/pkg/protocols/http/signer/aws-sign.go index bf6e15d3e..413f4688c 100644 --- a/pkg/protocols/http/signer/aws-sign.go +++ b/pkg/protocols/http/signer/aws-sign.go @@ -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 errkit.Wrap(err, "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) diff --git a/pkg/protocols/http/utils.go b/pkg/protocols/http/utils.go index 547b32dab..781dc61a3 100644 --- a/pkg/protocols/http/utils.go +++ b/pkg/protocols/http/utils.go @@ -1,7 +1,6 @@ package http import ( - "fmt" "io" "strings" @@ -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, errkit.Wrapf(err, "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, errkit.Wrapf(err, "could not dump request: %v", reqURL) } return bin, nil } diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index 573855ab5..9925c3103 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -127,14 +127,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 errkit.Newf("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 errkit.New("'Port' variable cannot contain any dsl expressions") } if request.Init != "" { @@ -218,11 +218,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 errkit.Newf("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 errkit.Newf("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 +239,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 errkit.Newf("could not compile pre-condition: %s", err) } request.preConditionCompiled = preConditionCompiled } @@ -248,7 +248,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 errkit.Newf("could not compile javascript code: %s", err) } request.scriptCompiled = scriptCompiled } diff --git a/pkg/protocols/network/network.go b/pkg/protocols/network/network.go index f1adc90c2..4a5088f64 100644 --- a/pkg/protocols/network/network.go +++ b/pkg/protocols/network/network.go @@ -1,7 +1,6 @@ package network import ( - "fmt" "strconv" "strings" @@ -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 errkit.Wrapf(err, "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 errkit.Newf("port %v is not in valid range", portInt) } request.ports = append(request.ports, port) } diff --git a/pkg/protocols/network/request.go b/pkg/protocols/network/request.go index 63e1bfb59..c8a3dd9b3 100644 --- a/pkg/protocols/network/request.go +++ b/pkg/protocols/network/request.go @@ -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 errkit.Wrap(err, "could not read response from connection") } responseBuilder.Write(buffer) diff --git a/pkg/protocols/ssl/ssl.go b/pkg/protocols/ssl/ssl.go index aa4a02616..c18eebc64 100644 --- a/pkg/protocols/ssl/ssl.go +++ b/pkg/protocols/ssl/ssl.go @@ -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 errkit.Wrap(err, "could not get network client") } 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 errkit.Newf("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 errkit.New("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 errkit.Newf("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 errkit.Wrap(err, "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 errkit.Wrap(err, "could not connect to server") } 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 errkit.Newf("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 errkit.Newf("certificate response cannot be parsed into a struct: %v", response.CertificateResponse) } responseParsed = structs.New(response.CertificateResponse) diff --git a/pkg/reporting/exporters/markdown/util/markdown_utils.go b/pkg/reporting/exporters/markdown/util/markdown_utils.go index 2ec5d8f9f..bbe1b82c3 100644 --- a/pkg/reporting/exporters/markdown/util/markdown_utils.go +++ b/pkg/reporting/exporters/markdown/util/markdown_utils.go @@ -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 "", errkit.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 "", errkit.New("Too many columns for the given headers") } } diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index 30de6ad87..a048e9478 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -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, errkit.Wrapf(err, "could not create reporting client: %v", 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, errkit.Wrapf(err, "could not create reporting client: %v", 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, errkit.Wrapf(err, "could not create reporting client: %v", 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, errkit.Wrapf(err, "could not create reporting client: %v", 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, errkit.Wrapf(err, "could not create reporting client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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, errkit.Wrapf(err, "could not create export client: %v", 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 errkit.Wrap(err, "could not create config file") } defer func() { _ = reportingFile.Close() diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index 8a8d69675..a9730043e 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -491,7 +491,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, errkit.Wrapf(err, "failed to parse %s", template.Path) } if utils.IsBlank(template.Info.Name) { @@ -551,7 +551,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, errkit.Wrapf(err, "failed to load file refs for %s", template.ID) } if err := template.compileProtocolRequests(template.Options); err != nil { diff --git a/pkg/templates/parser.go b/pkg/templates/parser.go index bf24308e7..02d40cc58 100644 --- a/pkg/templates/parser.go +++ b/pkg/templates/parser.go @@ -12,6 +12,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/utils/json" "github.com/projectdiscovery/nuclei/v3/pkg/utils/stats" yamlutil "github.com/projectdiscovery/nuclei/v3/pkg/utils/yaml" + "github.com/projectdiscovery/utils/errkit" fileutil "github.com/projectdiscovery/utils/file" "gopkg.in/yaml.v2" @@ -82,7 +83,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, errkit.Newf("Could not load template %s: %s", templatePath, templateParseError) } template, ok := t.(*Template) if !ok { @@ -96,13 +97,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, errkit.Newf("Could not load template %s: %s", templatePath, validationError) } ret, err := isTemplateInfoMetadataMatch(tagFilter, template, extraTags) if err != nil { checkOpenFileError(err) - return ret, ErrCouldNotLoadTemplate(templatePath, err.Error()) + return ret, errkit.Newf("Could not load template %s: %s", templatePath, err) } // if template loaded then check the template for optional fields to add warnings if ret { @@ -110,7 +111,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, errkit.Newf("Could not load template %s: %s", templatePath, validationWarning) } } return ret, nil diff --git a/pkg/templates/parser_error.go b/pkg/templates/parser_error.go index eaf174cbc..2a9869419 100644 --- a/pkg/templates/parser_error.go +++ b/pkg/templates/parser_error.go @@ -1,28 +1,13 @@ package templates import ( - "fmt" - "github.com/projectdiscovery/utils/errkit" ) -// 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 = errkit.New("mandatory field is missing") + ErrInvalidField = errkit.New("invalid field format") + ErrWarningFieldMissing = errkit.New("field is missing") + ErrCouldNotLoadTemplate = errkit.New("could not load template") + ErrLoadedWithWarnings = errkit.New("loaded template with syntax warning") +) diff --git a/pkg/templates/parser_validate.go b/pkg/templates/parser_validate.go index 3911bbb22..1a6609da3 100644 --- a/pkg/templates/parser_validate.go +++ b/pkg/templates/parser_validate.go @@ -5,6 +5,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/templates/types" "github.com/projectdiscovery/nuclei/v3/pkg/utils" + "github.com/projectdiscovery/utils/errkit" ) // validateTemplateMandatoryFields validates the mandatory fields of a template @@ -15,17 +16,17 @@ func validateTemplateMandatoryFields(template *Template) error { var validateErrors []error if utils.IsBlank(info.Name) { - validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("name")) + validateErrors = append(validateErrors, errkit.Newf("mandatory '%s' field is missing", "name")) } if info.Authors.IsEmpty() { - validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("author")) + validateErrors = append(validateErrors, errkit.Newf("mandatory '%s' field is missing", "author")) } if template.ID == "" { - validateErrors = append(validateErrors, ErrMandatoryFieldMissingFmt("id")) + validateErrors = append(validateErrors, errkit.Newf("mandatory '%s' field is missing", "id")) } else if !ReTemplateID.MatchString(template.ID) { - validateErrors = append(validateErrors, ErrInvalidField("id", ReTemplateID.String())) + validateErrors = append(validateErrors, errkit.Newf("invalid field format for '%s' (allowed format is %s)", "id", ReTemplateID.String())) } if len(validateErrors) > 0 { @@ -53,7 +54,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, errkit.Newf("field '%s' is missing", "severity")) } if len(warnings) > 0 { diff --git a/pkg/templates/signer/default.go b/pkg/templates/signer/default.go index 174bda18c..a56facba6 100644 --- a/pkg/templates/signer/default.go +++ b/pkg/templates/signer/default.go @@ -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 errkit.New("signer is nil") } DefaultTemplateVerifiers = append(DefaultTemplateVerifiers, s) return nil diff --git a/pkg/templates/signer/tmpl_signer.go b/pkg/templates/signer/tmpl_signer.go index bb3d26c48..590cf94b2 100644 --- a/pkg/templates/signer/tmpl_signer.go +++ b/pkg/templates/signer/tmpl_signer.go @@ -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 "", errkit.New("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 "", errkit.New("re-signing code templates are not allowed for security reasons.") } } } diff --git a/pkg/templates/template_sign.go b/pkg/templates/template_sign.go index e6647a335..9e46769f5 100644 --- a/pkg/templates/template_sign.go +++ b/pkg/templates/template_sign.go @@ -28,7 +28,7 @@ var ( _ = protocolstate.Init(defaultOpts) _ = protocolinit.Init(defaultOpts) }) - ErrNotATemplate = errkit.New("signer: given filePath is not a template").Build() + ErrNotATemplate = errkit.New("given filePath is not a template", "tag", "signer") ) // 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 errkit.Wrap(err, "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, errkit.Wrap(err, "failed to parse template") } return template, bin, nil } diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index 418234751..74818557e 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -2,7 +2,6 @@ package templates import ( - "fmt" "io" "path/filepath" "strconv" @@ -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 errkit.New("template id must match expression %v", ReTemplateID, "tag", "invalid_template") } info := template.Info if utils.IsBlank(info.Name) { - return errkit.New("invalid template: no template name field provided").Build() + return errkit.New("no template name field provided", "tag", "invalid_template") } if info.Authors.IsEmpty() { - return errkit.New("invalid template: no template author field provided").Build() + return errkit.New("no template author field provided", "tag", "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 errkit.New("use http or requests, both are not supported", "tag", "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 errkit.New("use tcp or network, both are not supported", "tag", "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 errkit.Wrapf(err, "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 errkit.Wrapf(err, "failed to unmarshal multi protocol template %s", template.ID) } arr := []string{} for k := range tempMap { diff --git a/pkg/testutils/fuzzplayground/sqli_test.go b/pkg/testutils/fuzzplayground/sqli_test.go new file mode 100644 index 000000000..0d9a3360b --- /dev/null +++ b/pkg/testutils/fuzzplayground/sqli_test.go @@ -0,0 +1,92 @@ +package fuzzplayground + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSQLInjectionBehavior(t *testing.T) { + server := GetPlaygroundServer() + ts := httptest.NewServer(server) + defer ts.Close() + + tests := []struct { + name string + path string + expectedStatus int + shouldContainAdmin bool + }{ + { + name: "Normal request", + path: "/user/75/profile", // User 75 exists and has role 'user' + expectedStatus: 200, + shouldContainAdmin: false, + }, + { + name: "SQL injection with OR 1=1", + path: "/user/75 OR 1=1/profile", + expectedStatus: 200, // Should work but might return first user (admin) + shouldContainAdmin: true, // Should return admin user data + }, + { + name: "SQL injection with UNION", + path: "/user/1 UNION SELECT 1,'admin',30,'admin'/profile", + expectedStatus: 200, + shouldContainAdmin: true, + }, + { + name: "Template payload test - OR True with 75", + path: "/user/75 OR True/profile", // What the template actually sends + expectedStatus: 200, // Actually works! + shouldContainAdmin: true, // Let's see if it returns admin + }, + { + name: "Template payload test - OR True with 55 (non-existent)", + path: "/user/55 OR True/profile", // What the template should actually send + expectedStatus: 200, // Should work due to SQL injection + shouldContainAdmin: true, // Should return admin due to OR True + }, + { + name: "Test original user 55 issue", + path: "/user/55/profile", // This should fail because user 55 doesn't exist + expectedStatus: 500, + shouldContainAdmin: false, + }, + { + name: "Invalid ID - non-existent", + path: "/user/999/profile", + expectedStatus: 500, // Should error due to no such user + shouldContainAdmin: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resp, err := http.Get(ts.URL + tt.path) + require.NoError(t, err) + defer func() { + if err := resp.Body.Close(); err != nil { + t.Logf("Failed to close response body: %v", err) + } + }() + + require.Equal(t, tt.expectedStatus, resp.StatusCode) + + body := make([]byte, 1024) + n, _ := resp.Body.Read(body) + bodyStr := string(body[:n]) + + fmt.Printf("Request: %s\n", tt.path) + fmt.Printf("Status: %d\n", resp.StatusCode) + fmt.Printf("Response: %s\n\n", bodyStr) + + if tt.shouldContainAdmin { + require.Contains(t, bodyStr, "admin") + } + }) + } +} \ No newline at end of file diff --git a/pkg/tmplexec/flow/flow_executor.go b/pkg/tmplexec/flow/flow_executor.go index 860e96292..cb9c70b52 100644 --- a/pkg/tmplexec/flow/flow_executor.go +++ b/pkg/tmplexec/flow/flow_executor.go @@ -22,10 +22,10 @@ import ( "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 = errkit.New("invalid request id 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 errkit.Wrapf(err, "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 errkit.Wrap(runtimeErr, "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, errkit.Wrapf(err, "failed to execute %v protocol", proto)) } return multierr.Combine(errs...) } diff --git a/pkg/tmplexec/flow/flow_internal.go b/pkg/tmplexec/flow/flow_internal.go index 249f324c6..c46662516 100644 --- a/pkg/tmplexec/flow/flow_internal.go +++ b/pkg/tmplexec/flow/flow_internal.go @@ -7,6 +7,7 @@ import ( "github.com/Mzack9999/goja" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" + "github.com/projectdiscovery/utils/errkit" mapsutil "github.com/projectdiscovery/utils/maps" ) @@ -61,7 +62,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, errkit.Newf("[%s] invalid request id '%s' provided", f.options.TemplateID, id)); err != nil { f.ctx.LogError(fmt.Errorf("failed to store flow runtime errors got %v", err)) } return matcherStatus.Load() diff --git a/pkg/types/types.go b/pkg/types/types.go index 4d009db51..48c186c84 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -1,7 +1,6 @@ package types import ( - "fmt" "io" "os" "path/filepath" @@ -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, errkit.Wrapf(err, "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 "", errkit.Wrapf(err, "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 "", errkit.Wrapf(err, "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 "", errkit.Newf("access to helper file %v denied", helperFilePath) } // SetExecutionID sets the execution ID for the options From a1b5a0ed994350de1254cd91651b33f4339445e6 Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Mon, 25 Aug 2025 15:12:51 +0700 Subject: [PATCH 093/135] fix(fuzz): handles duplicate multipart form field names (#6404) * fix: handle duplicate field names in multipart form encoding * fix(fuzz): handles `[]any` type in `*MultiPartForm.Encode` Signed-off-by: Dwi Siswanto * test(fuzz): adds panic recovery & display encoded out Signed-off-by: Dwi Siswanto * fix(fuzz): incorrectly treated mixed type field in `*MultiPartForm.Encode` Signed-off-by: Dwi Siswanto * test(fuzz): refactor compare w decoded instead Signed-off-by: Dwi Siswanto * chore(fuzz): prealloc for `[]any` type Signed-off-by: Dwi Siswanto * fix(fuzz): treats nil value as empty string Signed-off-by: Dwi Siswanto * chore(fuzz): rm early error return for non-array file Signed-off-by: Dwi Siswanto * test(fuzz): adds `TestMultiPartFormFileUpload` test Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto Co-authored-by: yusei-wy <31252054+yusei-wy@users.noreply.github.com> --- pkg/fuzz/dataformat/multipart.go | 71 +++++--- pkg/fuzz/dataformat/multipart_test.go | 242 ++++++++++++++++++++++++++ 2 files changed, 287 insertions(+), 26 deletions(-) create mode 100644 pkg/fuzz/dataformat/multipart_test.go diff --git a/pkg/fuzz/dataformat/multipart.go b/pkg/fuzz/dataformat/multipart.go index 97af6207f..483814f28 100644 --- a/pkg/fuzz/dataformat/multipart.go +++ b/pkg/fuzz/dataformat/multipart.go @@ -49,42 +49,61 @@ func (m *MultiPartForm) Encode(data KV) (string, error) { var fw io.Writer var err error - if filesArray, ok := value.([]interface{}); ok { - fileMetadata, ok := m.filesMetadata[key] - if !ok { - Itererr = fmt.Errorf("file metadata not found for key %s", key) - return false - } + if fileMetadata, ok := m.filesMetadata[key]; ok { + if filesArray, isArray := value.([]any); isArray { + for _, file := range filesArray { + h := make(textproto.MIMEHeader) + h.Set("Content-Disposition", + fmt.Sprintf(`form-data; name=%q; filename=%q`, + key, fileMetadata.Filename)) + h.Set("Content-Type", fileMetadata.ContentType) - for _, file := range filesArray { - h := make(textproto.MIMEHeader) - h.Set("Content-Disposition", - fmt.Sprintf(`form-data; name=%q; filename=%q`, - key, fileMetadata.Filename)) - h.Set("Content-Type", fileMetadata.ContentType) + if fw, err = w.CreatePart(h); err != nil { + Itererr = err + return false + } - if fw, err = w.CreatePart(h); err != nil { - Itererr = err - return false + if _, err = fw.Write([]byte(file.(string))); err != nil { + Itererr = err + return false + } } - if _, err = fw.Write([]byte(file.(string))); err != nil { - Itererr = err - return false - } + return true } - return true } // Add field - if fw, err = w.CreateFormField(key); err != nil { - Itererr = err - return false + var values []string + switch v := value.(type) { + case nil: + values = []string{""} + case string: + values = []string{v} + case []string: + values = v + case []any: + values = make([]string, len(v)) + for i, item := range v { + if item == nil { + values[i] = "" + } else { + values[i] = fmt.Sprint(item) + } + } + default: + values = []string{fmt.Sprintf("%v", v)} } - if _, err = fw.Write([]byte(value.(string))); err != nil { - Itererr = err - return false + for _, val := range values { + if fw, err = w.CreateFormField(key); err != nil { + Itererr = err + return false + } + if _, err = fw.Write([]byte(val)); err != nil { + Itererr = err + return false + } } return true }) diff --git a/pkg/fuzz/dataformat/multipart_test.go b/pkg/fuzz/dataformat/multipart_test.go new file mode 100644 index 000000000..a649ee13a --- /dev/null +++ b/pkg/fuzz/dataformat/multipart_test.go @@ -0,0 +1,242 @@ +package dataformat + +import ( + "testing" + + mapsutil "github.com/projectdiscovery/utils/maps" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMultiPartFormEncode(t *testing.T) { + tests := []struct { + name string + fields map[string]any + wantErr bool + expected map[string]any + }{ + { + name: "duplicate fields ([]string) - checkbox scenario", + fields: map[string]any{ + "interests": []string{"sports", "music", "reading"}, + "colors": []string{"red", "blue"}, + }, + expected: map[string]any{ + "interests": []string{"sports", "music", "reading"}, + "colors": []string{"red", "blue"}, + }, + }, + { + name: "single string fields - backward compatibility", + fields: map[string]any{ + "username": "john", + "email": "john@example.com", + }, + expected: map[string]any{ + "username": "john", + "email": "john@example.com", + }, + }, + { + name: "mixed types", + fields: map[string]any{ + "string": "text", + "array": []string{"item1", "item2"}, + "number": 42, // tests fmt.Sprint fallback + "float": 3.14, // tests float conversion + "boolean": true, // tests boolean conversion + "zero": 0, // tests zero value + "emptyStr": "", // tests empty string + "negative": -123, // tests negative number + "nil": nil, // tests nil value + "mixedArray": []any{"str", 123, false, nil}, // tests mixed type array + }, + expected: map[string]any{ + "string": "text", + "array": []string{"item1", "item2"}, + "number": "42", // numbers are converted to strings in multipart + "float": "3.14", // floats are converted to strings + "boolean": "true", // booleans are converted to strings + "zero": "0", // zero value converted to string + "emptyStr": "", // empty string remains empty + "negative": "-123", // negative numbers converted to strings + "nil": "", // nil values converted to "" string + "mixedArray": []string{"str", "123", "false", ""}, // mixed array converted to string array + }, + }, + { + name: "empty array - should not appear in output", + fields: map[string]any{ + "emptyArray": []string{}, + "normalField": "value", + }, + expected: map[string]any{ + "normalField": "value", + // emptyArray should not appear in decoded output + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("Test panicked: %v", r) + } + }() + + form := NewMultiPartForm() + form.boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW" + + kv := mapsutil.NewOrderedMap[string, any]() + for k, v := range tt.fields { + kv.Set(k, v) + } + + encoded, err := form.Encode(KVOrderedMap(&kv)) + + if tt.wantErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + + // Decode the encoded multipart data + decoded, err := form.Decode(encoded) + require.NoError(t, err) + + // Compare decoded values with expected values + for expectedKey, expectedValue := range tt.expected { + actualValue := decoded.Get(expectedKey) + switch expected := expectedValue.(type) { + case []string: + actual, ok := actualValue.([]string) + require.True(t, ok, "Expected []string for key %s, got %T", expectedKey, actualValue) + assert.ElementsMatch(t, expected, actual, "Values mismatch for key %s", expectedKey) + case []any: + actual, ok := actualValue.([]any) + require.True(t, ok, "Expected []any for key %s, got %T", expectedKey, actualValue) + assert.ElementsMatch(t, expected, actual, "Values mismatch for key %s", expectedKey) + case string: + actual, ok := actualValue.(string) + require.True(t, ok, "Expected string for key %s, got %T", expectedKey, actualValue) + assert.Equal(t, expected, actual, "Values mismatch for key %s", expectedKey) + default: + assert.Equal(t, expected, actualValue, "Values mismatch for key %s", expectedKey) + } + } + + // Ensure no unexpected keys are present in decoded output + decoded.Iterate(func(key string, value any) bool { + _, exists := tt.expected[key] + assert.True(t, exists, "Unexpected key %s found in decoded output", key) + return true + }) + + t.Logf("Encoded output:\n%s", encoded) + }) + } +} + +func TestMultiPartFormRoundTrip(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("Test panicked: %v", r) + } + }() + + form := NewMultiPartForm() + form.boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW" + + original := mapsutil.NewOrderedMap[string, any]() + original.Set("username", "john") + original.Set("interests", []string{"sports", "music", "reading"}) + + encoded, err := form.Encode(KVOrderedMap(&original)) + require.NoError(t, err) + + decoded, err := form.Decode(encoded) + require.NoError(t, err) + + assert.Equal(t, "john", decoded.Get("username")) + assert.ElementsMatch(t, []string{"sports", "music", "reading"}, decoded.Get("interests")) + + t.Logf("Encoded output:\n%s", encoded) +} + +func TestMultiPartFormFileUpload(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("Test panicked: %v", r) + } + }() + + // Test decoding of a manually crafted multipart form with files + form := NewMultiPartForm() + form.boundary = "----WebKitFormBoundaryFileUploadTest" + + // Manually craft a multipart form with file uploads + multipartData := `------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="name" + +John Doe +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="email" + +john@example.com +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="profile_picture"; filename="profile.jpg" +Content-Type: image/jpeg + +fake_jpeg_binary_data_here +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="documents"; filename="resume.pdf" +Content-Type: application/pdf + +fake_pdf_content_1 +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="documents"; filename="cover_letter.pdf" +Content-Type: application/pdf + +fake_pdf_content_2 +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="skills" + +Go +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="skills" + +JavaScript +------WebKitFormBoundaryFileUploadTest +Content-Disposition: form-data; name="skills" + +Python +------WebKitFormBoundaryFileUploadTest-- +` + + // Test decoding + decoded, err := form.Decode(multipartData) + require.NoError(t, err) + + // Verify regular fields + assert.Equal(t, "John Doe", decoded.Get("name")) + assert.Equal(t, "john@example.com", decoded.Get("email")) + assert.Equal(t, []string{"Go", "JavaScript", "Python"}, decoded.Get("skills")) + + // Verify file fields + profilePicture := decoded.Get("profile_picture") + require.NotNil(t, profilePicture) + profileArray, ok := profilePicture.([]interface{}) + require.True(t, ok, "Expected []interface{} for profile_picture") + require.Len(t, profileArray, 1) + assert.Equal(t, "fake_jpeg_binary_data_here", profileArray[0]) + + documents := decoded.Get("documents") + require.NotNil(t, documents) + documentsArray, ok := documents.([]interface{}) + require.True(t, ok, "Expected []interface{} for documents") + require.Len(t, documentsArray, 2) + assert.Contains(t, documentsArray, "fake_pdf_content_1") + assert.Contains(t, documentsArray, "fake_pdf_content_2") +} From 0f7b33cebf4d9980199cf8f21b6aec8ce9ed5c89 Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Mon, 25 Aug 2025 13:56:03 +0530 Subject: [PATCH 094/135] limited test, instead of all --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 6aaa55de1..bfb0b5a64 100644 --- a/Makefile +++ b/Makefile @@ -150,6 +150,10 @@ template-validate: -et .github/ \ -et helpers/payloads/ \ -et http/technologies \ + -t dns \ + -t ssl \ + -t network \ + -t http/exposures \ -ept code ./bin/nuclei -validate \ -w workflows \ From efcef5568173f839fed4281d105770e8d8688d8c Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 25 Aug 2025 13:59:01 +0200 Subject: [PATCH 095/135] lint --- pkg/operators/matchers/match.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/operators/matchers/match.go b/pkg/operators/matchers/match.go index e74270ef1..93ba0b596 100644 --- a/pkg/operators/matchers/match.go +++ b/pkg/operators/matchers/match.go @@ -316,7 +316,7 @@ func (m *Matcher) ignoreErr(err error) bool { if showDSLErr { return false } - if stringsutil.ContainsAny(err.Error(), "No parameter", dslRepo.ErrParsingArg.Error()) { + if stringsutil.ContainsAny(err.Error(), "No parameter", dslRepo.ErrParsingArg.Error()) { //nolint return true } return false From f20f95f67e1de02f77be203fe071a61f9dcfbbd1 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 25 Aug 2025 15:13:23 +0200 Subject: [PATCH 096/135] integration test --- cmd/integration-test/javascript.go | 52 +++++++++++++++++++ .../protocols/javascript/vnc-pass-brute.yaml | 38 ++++++++++++++ pkg/js/libs/vnc/vnc.go | 7 ++- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 integration_tests/protocols/javascript/vnc-pass-brute.yaml diff --git a/cmd/integration-test/javascript.go b/cmd/integration-test/javascript.go index e45f122c3..064162dc8 100644 --- a/cmd/integration-test/javascript.go +++ b/cmd/integration-test/javascript.go @@ -15,11 +15,13 @@ var jsTestcases = []TestCaseInfo{ {Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, {Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}}, {Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNetHttps{}}, + {Path: "protocols/javascript/vnc-pass-brute.yaml", TestCase: &javascriptVncPassBrute{}}, } var ( redisResource *dockertest.Resource sshResource *dockertest.Resource + vncResource *dockertest.Resource pool *dockertest.Pool defaultRetry = 3 ) @@ -98,6 +100,38 @@ func (j *javascriptSSHServerFingerprint) Execute(filePath string) error { return multierr.Combine(errs...) } +type javascriptVncPassBrute struct{} + +func (j *javascriptVncPassBrute) Execute(filePath string) error { + if vncResource == nil || pool == nil { + // skip test as vnc is not running + return nil + } + tempPort := vncResource.GetPort("5900/tcp") + finalURL := "localhost:" + tempPort + defer purge(vncResource) + errs := []error{} + for i := 0; i < defaultRetry; i++ { + results := []string{} + var err error + _ = pool.Retry(func() error { + //let ssh server start + time.Sleep(3 * time.Second) + results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug) + return nil + }) + if err != nil { + return err + } + if err := expectResultsCount(results, 1); err == nil { + return nil + } else { + errs = append(errs, err) + } + } + return multierr.Combine(errs...) +} + // purge any given resource if it is not nil func purge(resource *dockertest.Resource) { if resource != nil && pool != nil { @@ -163,4 +197,22 @@ func init() { if err := sshResource.Expire(30); err != nil { log.Printf("Could not expire resource: %s", err) } + + // setup a temporary vnc server + vncResource, err = pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "dorowu/ubuntu-desktop-lxde-vnc", + Tag: "latest", + Env: []string{ + "VNC_PASSWORD=mysecret", + }, + Platform: "linux/amd64", + }) + if err != nil { + log.Printf("Could not start resource: %s", err) + return + } + // by default expire after 30 sec + if err := vncResource.Expire(30); err != nil { + log.Printf("Could not expire resource: %s", err) + } } diff --git a/integration_tests/protocols/javascript/vnc-pass-brute.yaml b/integration_tests/protocols/javascript/vnc-pass-brute.yaml new file mode 100644 index 000000000..68cb9df62 --- /dev/null +++ b/integration_tests/protocols/javascript/vnc-pass-brute.yaml @@ -0,0 +1,38 @@ +id: vnc-password-test + +info: + name: VNC Password Authentication Test + author: pdteam + severity: high + description: | + Tests VNC authentication with correct and incorrect passwords. + metadata: + shodan-query: product:"vnc" + tags: js,network,vnc,authentication + +javascript: + - pre-condition: | + isPortOpen(Host,Port) + + code: | + let vnc = require('nuclei/vnc'); + let client = new vnc.VNCClient(); + client.Connect(Host, Port, Password); + + args: + Host: "{{Host}}" + Port: "5900" + Password: "{{passwords}}" + payloads: + passwords: + - "" + - root + - password + - admin + - mysecret + stop-at-first-match: true + + matchers: + - type: dsl + dsl: + - "success == true" diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index c1aaf8103..16103c30d 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -83,7 +83,7 @@ func connect(executionId string, host string, port int, password string) (bool, vncConfig := vnclib.NewClientConfig(password) // Attempt to connect and authenticate - _, err = vnclib.Connect(context.TODO(), conn, vncConfig) + c, err := vnclib.Connect(context.TODO(), conn, vncConfig) if err != nil { // Check for specific authentication errors if isAuthError(err) { @@ -91,6 +91,9 @@ func connect(executionId string, host string, port int, password string) (bool, } return false, err // Connection or other error } + if c != nil { + _ = c.Close() + } return true, nil } @@ -103,7 +106,7 @@ func isAuthError(err error) bool { // Check for common VNC authentication error messages errStr := err.Error() - return stringsutil.ContainsAny(errStr, "authentication", "auth", "password", "invalid", "failed") + return stringsutil.ContainsAnyI(errStr, "authentication", "auth", "password", "invalid", "failed") } // IsVNC checks if a host is running a VNC server. From e83382d4e45ef24a23b3288ae061563e88210c69 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 25 Aug 2025 15:33:21 +0200 Subject: [PATCH 097/135] lint --- pkg/js/libs/vnc/vnc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index 16103c30d..63c3e6a37 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -60,7 +60,7 @@ func connect(executionId string, host string, port int, password string) (bool, } 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) From 5b7debf349a4f0e4af22874b9e92d9a913bb3188 Mon Sep 17 00:00:00 2001 From: zy9ard3 <67743789+zy9ard3@users.noreply.github.com> Date: Tue, 26 Aug 2025 09:05:31 +0530 Subject: [PATCH 098/135] Update pkg/external/customtemplates/github.go Co-authored-by: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> --- pkg/external/customtemplates/github.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/external/customtemplates/github.go b/pkg/external/customtemplates/github.go index 338a4cb80..f6fc474ef 100644 --- a/pkg/external/customtemplates/github.go +++ b/pkg/external/customtemplates/github.go @@ -53,7 +53,7 @@ func (customTemplate *customTemplateGitHubRepo) Update(ctx context.Context) { } err := customTemplate.pullChanges(clonePath, customTemplate.githubToken) if err != nil { - if strings.Contains(err.Error(), "already up-to-date") { + if errors.Is(err, git.NoErrAlreadyUpToDate) { gologger.Info().Msgf("%s", err) } else { gologger.Error().Msgf("%s", err) From 1f0aef970ca4ad2133452ce6558172b58d95f115 Mon Sep 17 00:00:00 2001 From: zy9ard3 <67743789+zy9ard3@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:48:10 +0530 Subject: [PATCH 099/135] fix for error.Is false return --- pkg/external/customtemplates/github.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/external/customtemplates/github.go b/pkg/external/customtemplates/github.go index f6fc474ef..499649494 100644 --- a/pkg/external/customtemplates/github.go +++ b/pkg/external/customtemplates/github.go @@ -191,7 +191,7 @@ func (ctr *customTemplateGitHubRepo) pullChanges(repoPath, githubToken string) e err = w.Pull(pullOpts) if err != nil { - return errors.Errorf("%s/%s: %s", ctr.owner, ctr.reponame, err.Error()) + return errors.Wrapf(err, "%s/%s", ctr.owner, ctr.reponame) } return nil From 776cb4fcf26279490e655d60977707477e001e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Tue, 26 Aug 2025 10:04:36 +0300 Subject: [PATCH 100/135] bump httpx version --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 191fd9b41..9be9121d4 100644 --- a/go.mod +++ b/go.mod @@ -37,9 +37,9 @@ require ( github.com/valyala/fasttemplate v1.2.2 github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39 go.uber.org/multierr v1.11.0 - golang.org/x/net v0.41.0 + golang.org/x/net v0.42.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/text v0.26.0 + golang.org/x/text v0.27.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -95,7 +95,7 @@ require ( github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/gostruct v0.0.2 github.com/projectdiscovery/gozero v0.0.3 - github.com/projectdiscovery/httpx v1.7.0 + github.com/projectdiscovery/httpx v1.7.1 github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 github.com/projectdiscovery/networkpolicy v0.1.20 @@ -106,7 +106,7 @@ require ( github.com/projectdiscovery/uncover v1.1.0 github.com/projectdiscovery/useragent v0.0.101 github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4 - github.com/projectdiscovery/wappalyzergo v0.2.36 + github.com/projectdiscovery/wappalyzergo v0.2.37 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -116,7 +116,7 @@ require ( github.com/zmap/zgrab2 v0.1.8 gitlab.com/gitlab-org/api/client-go v0.130.1 go.mongodb.org/mongo-driver v1.17.4 - golang.org/x/term v0.32.0 + golang.org/x/term v0.33.0 gopkg.in/yaml.v3 v3.0.1 moul.io/http2curl v1.0.0 ) @@ -294,7 +294,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.26 // indirect + github.com/projectdiscovery/cdncheck v1.1.27 // indirect 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 @@ -339,7 +339,7 @@ require ( github.com/zeebo/blake3 v0.2.3 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/sync v0.15.0 // indirect + golang.org/x/sync v0.16.0 // indirect gopkg.in/djherbis/times.v1 v1.3.0 // indirect mellium.im/sasl v0.3.2 // indirect ) @@ -363,10 +363,10 @@ require ( go.etcd.io/bbolt v1.3.10 // indirect go.uber.org/zap v1.25.0 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/crypto v0.39.0 // indirect + golang.org/x/crypto v0.40.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b golang.org/x/mod v0.25.0 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.34.0 // indirect golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.34.0 google.golang.org/protobuf v1.35.1 // indirect diff --git a/go.sum b/go.sum index 3551fb73c..aea0ca67e 100644 --- a/go.sum +++ b/go.sum @@ -763,8 +763,8 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.26 h1:R6JxzU3ptGNrzzvS261xHWssDt9GlOCWXkuet1huOyA= -github.com/projectdiscovery/cdncheck v1.1.26/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.27 h1:ZuSyIG0kxI5voWIZzIYVDm3DIe+vN63oPb8d5GIdRLA= +github.com/projectdiscovery/cdncheck v1.1.27/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= github.com/projectdiscovery/dsl v0.5.0 h1:3HHY14FNmdwWXq3pi9dd8JjUHQzskZjLD/pZKVx5Vi4= @@ -789,8 +789,8 @@ github.com/projectdiscovery/gozero v0.0.3 h1:tsYkrSvWw4WdIUJyisd4MB1vRiw1X57TuVV 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/httpx v1.7.0 h1:s7ZgF2ZAt9pQYkBuY5F6SjyNYbYrl7eiIzOm/6hBZ/E= -github.com/projectdiscovery/httpx v1.7.0/go.mod h1:D0HLzSy+/G6w01FtRORGyfwVwWlUPAFIc8wyEj/lcVg= +github.com/projectdiscovery/httpx v1.7.1 h1:XmhUGGUdmpWWXyQC8utV9gyHVrjzXBcT2SAUOgFOQV8= +github.com/projectdiscovery/httpx v1.7.1/go.mod h1:fejxELITLvQ0uXB/pnBiekjMmGdoE7+7p+DpIYhAhJU= github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI= github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc= github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8= @@ -825,8 +825,8 @@ github.com/projectdiscovery/useragent v0.0.101 h1:8A+XOJ/nIH+WqW8ogLxJ/psemGp8AT github.com/projectdiscovery/useragent v0.0.101/go.mod h1:RGoRw1BQ/lJnhYMbMpEKjyAAgCaDCr/+GsULo5yEJ2I= github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4 h1:qQMEhfxDsiZ+Ay3dj93FuMAa7yt1XE2bxDpPSTEz/P0= github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4/go.mod h1:ipzU2PHYP71MaMn4jllPOpdYpdMkFD0jE3Tjak4b4eM= -github.com/projectdiscovery/wappalyzergo v0.2.36 h1:g/E2gatdYcmLKk9R81vrkq4RdpACpYgN1fuyY3041eE= -github.com/projectdiscovery/wappalyzergo v0.2.36/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA= +github.com/projectdiscovery/wappalyzergo v0.2.37 h1:O4XgDKCWAXQT1mEJrLHX88vk+fCEUzNPdpJPAvvAhg0= +github.com/projectdiscovery/wappalyzergo v0.2.37/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1104,8 +1104,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1195,8 +1195,8 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1225,8 +1225,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1291,8 +1291,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1306,8 +1306,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1324,8 +1324,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 5063af46b184403bb079cfcf3867c5a96647b74d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 15:32:43 +0000 Subject: [PATCH 101/135] chore(deps): bump github.com/go-viper/mapstructure/v2 Bumps the go_modules group with 1 update in the / directory: [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure). Updates `github.com/go-viper/mapstructure/v2` from 2.3.0 to 2.4.0 - [Release notes](https://github.com/go-viper/mapstructure/releases) - [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md) - [Commits](https://github.com/go-viper/mapstructure/compare/v2.3.0...v2.4.0) --- updated-dependencies: - dependency-name: github.com/go-viper/mapstructure/v2 dependency-version: 2.4.0 dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 191fd9b41..db7fe22d6 100644 --- a/go.mod +++ b/go.mod @@ -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.4.0 // 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 diff --git a/go.sum b/go.sum index 3551fb73c..0c3beb503 100644 --- a/go.sum +++ b/go.sum @@ -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.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/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= From 8194fabcf8f71bf83b093e5a228c2409c114b4f2 Mon Sep 17 00:00:00 2001 From: Lorenzo Susini <49318629+loresuso@users.noreply.github.com> Date: Wed, 27 Aug 2025 00:55:31 +0200 Subject: [PATCH 102/135] =?UTF-8?q?test(reporting/exporters/mongo):=20add?= =?UTF-8?q?=20mongo=20integration=20test=20with=20test=E2=80=A6=20(#6237)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test(reporting/exporters/mongo): add mongo integration test with testcontainer-go module Signed-off-by: Lorenzo Susini * execute exportes only on linux --------- Signed-off-by: Lorenzo Susini Co-authored-by: Mzack9999 --- cmd/integration-test/exporters.go | 104 ++ cmd/integration-test/integration-test.go | 1 + go.mod | 73 +- go.sum | 1095 ++++++++++++++++++++-- 4 files changed, 1175 insertions(+), 98 deletions(-) create mode 100644 cmd/integration-test/exporters.go diff --git a/cmd/integration-test/exporters.go b/cmd/integration-test/exporters.go new file mode 100644 index 000000000..7890734f4 --- /dev/null +++ b/cmd/integration-test/exporters.go @@ -0,0 +1,104 @@ +package main + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/projectdiscovery/nuclei/v3/pkg/output" + "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo" + "github.com/testcontainers/testcontainers-go" + mongocontainer "github.com/testcontainers/testcontainers-go/modules/mongodb" + + osutil "github.com/projectdiscovery/utils/os" + mongoclient "go.mongodb.org/mongo-driver/mongo" + mongooptions "go.mongodb.org/mongo-driver/mongo/options" +) + +const ( + dbName = "test" + dbImage = "mongo:8" +) + +var exportersTestCases = []TestCaseInfo{ + {Path: "exporters/mongo", TestCase: &mongoExporter{}, DisableOn: func() bool { + return osutil.IsWindows() || osutil.IsOSX() + }}, +} + +type mongoExporter struct{} + +func (m *mongoExporter) Execute(filepath string) error { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + + // Start a MongoDB container + mongodbContainer, err := mongocontainer.Run(ctx, dbImage) + defer func() { + if err := testcontainers.TerminateContainer(mongodbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + if err != nil { + return fmt.Errorf("failed to start container: %w", err) + } + + connString, err := mongodbContainer.ConnectionString(ctx) + if err != nil { + return fmt.Errorf("failed to get connection string for MongoDB container: %s", err) + } + connString = connString + dbName + + // Create a MongoDB exporter and write a test result to the database + opts := mongo.Options{ + ConnectionString: connString, + CollectionName: "test", + BatchSize: 1, // Ensure we write the result immediately + } + + exporter, err := mongo.New(&opts) + if err != nil { + return fmt.Errorf("failed to create MongoDB exporter: %s", err) + } + defer func() { + if err := exporter.Close(); err != nil { + fmt.Printf("failed to close exporter: %s\n", err) + } + }() + + res := &output.ResultEvent{ + Request: "test request", + Response: "test response", + } + + err = exporter.Export(res) + if err != nil { + return fmt.Errorf("failed to export result event to MongoDB: %s", err) + } + + // Verify that the result was written to the database + clientOptions := mongooptions.Client().ApplyURI(connString) + client, err := mongoclient.Connect(ctx, clientOptions) + if err != nil { + return fmt.Errorf("error creating MongoDB client: %s", err) + } + defer func() { + if err := client.Disconnect(ctx); err != nil { + fmt.Printf("failed to disconnect from MongoDB: %s\n", err) + } + }() + + collection := client.Database(dbName).Collection(opts.CollectionName) + var actualRes output.ResultEvent + err = collection.FindOne(ctx, map[string]interface{}{"request": res.Request}).Decode(&actualRes) + if err != nil { + return fmt.Errorf("failed to find document in MongoDB: %s", err) + } + + if actualRes.Request != res.Request || actualRes.Response != res.Response { + return fmt.Errorf("exported result does not match expected result: got %v, want %v", actualRes, res) + } + + return nil +} diff --git a/cmd/integration-test/integration-test.go b/cmd/integration-test/integration-test.go index 545d5da41..10af587c0 100644 --- a/cmd/integration-test/integration-test.go +++ b/cmd/integration-test/integration-test.go @@ -57,6 +57,7 @@ var ( "flow": flowTestcases, "javascript": jsTestcases, "matcher-status": matcherStatusTestcases, + "exporters": exportersTestCases, } // flakyTests are run with a retry count of 3 flakyTests = map[string]bool{ diff --git a/go.mod b/go.mod index db7fe22d6..956121e53 100644 --- a/go.mod +++ b/go.mod @@ -37,9 +37,9 @@ require ( github.com/valyala/fasttemplate v1.2.2 github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39 go.uber.org/multierr v1.11.0 - golang.org/x/net v0.41.0 + golang.org/x/net v0.42.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/text v0.26.0 + golang.org/x/text v0.28.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -110,26 +110,28 @@ require ( github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.0 github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 + github.com/testcontainers/testcontainers-go v0.38.0 + github.com/testcontainers/testcontainers-go/modules/mongodb v0.37.0 github.com/yassinebenaid/godump v0.11.1 github.com/zmap/zgrab2 v0.1.8 gitlab.com/gitlab-org/api/client-go v0.130.1 go.mongodb.org/mongo-driver v1.17.4 - golang.org/x/term v0.32.0 + golang.org/x/term v0.34.0 gopkg.in/yaml.v3 v3.0.1 moul.io/http2curl v1.0.0 ) require ( aead.dev/minisign v0.2.0 // indirect - dario.cat/mergo v1.0.0 // indirect + dario.cat/mergo v1.0.2 // indirect filippo.io/edwards25519 v1.1.0 // indirect git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect github.com/42wim/httpsig v1.2.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -185,18 +187,26 @@ require ( github.com/cloudwego/base64x v0.1.5 // indirect github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect github.com/containerd/continuity v0.4.5 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/distribution/reference v0.6.0 // 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/go-connections v0.5.0 // indirect + github.com/docker/docker v28.3.3+incompatible // indirect + github.com/docker/go-connections v0.6.0 // indirect github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect + github.com/ebitengine/purego v0.8.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/fgprof v0.9.5 // indirect + github.com/felixge/httpsnoop v1.0.4 // 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.23.1 // indirect @@ -207,7 +217,9 @@ require ( github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -255,8 +267,9 @@ require ( github.com/logrusorgru/aurora/v4 v4.0.0 // indirect github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d // indirect github.com/mackerelio/go-osstat v0.2.4 // indirect + github.com/magiconair/properties v1.8.10 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -268,12 +281,17 @@ require ( github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/sys/user v0.3.0 // indirect - github.com/moby/term v0.5.0 // indirect + github.com/moby/go-archive v0.1.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/montanaflynn/stats v0.7.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/nwaples/rardecode/v2 v2.1.0 // indirect @@ -282,7 +300,7 @@ require ( github.com/olekukonko/errors v1.1.0 // indirect github.com/olekukonko/ll v0.0.9 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/runc v1.2.3 // indirect github.com/openrdap/rdap v0.9.1 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect @@ -291,7 +309,7 @@ require ( github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect github.com/projectdiscovery/cdncheck v1.1.26 // indirect @@ -302,6 +320,7 @@ require ( 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 + github.com/shirou/gopsutil/v4 v4.25.7 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect @@ -315,8 +334,8 @@ require ( github.com/tidwall/rtred v0.1.2 // indirect github.com/tidwall/tinyqueue v0.1.1 // indirect github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tklauser/go-sysconf v0.3.15 // indirect + github.com/tklauser/numcpus v0.10.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect github.com/ulikunitz/xz v0.5.12 // indirect @@ -337,9 +356,14 @@ require ( github.com/yuin/goldmark-emoji v1.0.5 // indirect github.com/zcalusic/sysinfo v1.0.2 // indirect github.com/zeebo/blake3 v0.2.3 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect + go.opentelemetry.io/otel v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/sync v0.15.0 // indirect + golang.org/x/sync v0.16.0 // indirect gopkg.in/djherbis/times.v1 v1.3.0 // indirect mellium.im/sasl v0.3.2 // indirect ) @@ -363,12 +387,12 @@ require ( go.etcd.io/bbolt v1.3.10 // indirect go.uber.org/zap v1.25.0 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/crypto v0.39.0 // indirect + golang.org/x/crypto v0.41.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b - golang.org/x/mod v0.25.0 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/sys v0.35.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.34.0 + golang.org/x/tools v0.35.0 google.golang.org/protobuf v1.35.1 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect @@ -382,3 +406,10 @@ require ( // https://go.dev/ref/mod#go-mod-file-retract retract v3.2.0 // retract due to broken js protocol issue + +// Fix genproto version conflicts +replace ( + google.golang.org/genproto => google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/genproto/googleapis/api => google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/genproto/googleapis/rpc => google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 +) diff --git a/go.sum b/go.sum index 0c3beb503..2c21f558e 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,12 @@ aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk= aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ= +cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -15,35 +17,274 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= +cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= +cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/accessapproval v1.7.11/go.mod h1:KGK3+CLDWm4BvjN0wFtZqdFUGhxlTvTF6PhAwQJGL4M= +cloud.google.com/go/accesscontextmanager v1.8.9/go.mod h1:IXvQesVgOC7aXgK9OpYFn5eWnzz8fazegIiJ5WnCOVw= +cloud.google.com/go/accesscontextmanager v1.8.11/go.mod h1:nwPysISS3KR5qXipAU6cW/UbDavDdTBBgPohbkhGSok= +cloud.google.com/go/aiplatform v1.68.0/go.mod h1:105MFA3svHjC3Oazl7yjXAmIR89LKhRAeNdnDKJczME= +cloud.google.com/go/analytics v0.23.6/go.mod h1:cFz5GwWHrWQi8OHKP9ep3Z4pvHgGcG9lPnFQ+8kXsNo= +cloud.google.com/go/apigateway v1.6.11/go.mod h1:4KsrYHn/kSWx8SNUgizvaz+lBZ4uZfU7mUDsGhmkWfM= +cloud.google.com/go/apigeeconnect v1.6.11/go.mod h1:iMQLTeKxtKL+sb0D+pFlS/TO6za2IUOh/cwMEtn/4g0= +cloud.google.com/go/apigeeregistry v0.8.9/go.mod h1:4XivwtSdfSO16XZdMEQDBCMCWDp3jkCBRhVgamQfLSA= +cloud.google.com/go/appengine v1.8.11/go.mod h1:xET3coaDUj+OP4TgnZlgQ+rG2R9fG2nblya13czP56Q= +cloud.google.com/go/area120 v0.8.11/go.mod h1:VBxJejRAJqeuzXQBbh5iHBYUkIjZk5UzFZLCXmzap2o= +cloud.google.com/go/artifactregistry v1.14.13/go.mod h1:zQ/T4xoAFPtcxshl+Q4TJBgsy7APYR/BLd2z3xEAqRA= +cloud.google.com/go/asset v1.19.5/go.mod h1:sqyLOYaLLfc4ACcn3YxqHno+J7lRt9NJTdO50zCUcY0= +cloud.google.com/go/assuredworkloads v1.11.11/go.mod h1:vaYs6+MHqJvLKYgZBOsuuOhBgNNIguhRU0Kt7JTGcnI= +cloud.google.com/go/auth v0.2.1/go.mod h1:khQRBNrvNoHiHhV1iu2x8fSnlNbCaVHilznW5MAI5GY= +cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= +cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= +cloud.google.com/go/auth v0.4.2/go.mod h1:Kqvlz1cf1sNA0D+sYJnkPQOP+JMHkuHeIgVmCRtZOLc= +cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= +cloud.google.com/go/auth v0.6.0/go.mod h1:b4acV+jLQDyjwm4OXHYjNvRi4jvGBzHWJRtJcy+2P4g= +cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= +cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw= +cloud.google.com/go/auth v0.7.2/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= +cloud.google.com/go/automl v1.13.11/go.mod h1:oMJdXRDOVC+Eq3PnGhhxSut5Hm9TSyVx1aLEOgerOw8= +cloud.google.com/go/baremetalsolution v1.2.10/go.mod h1:eO2c2NMRy5ytcNPhG78KPsWGNsX5W/tUsCOWmYihx6I= +cloud.google.com/go/batch v1.9.2/go.mod h1:smqwS4sleDJVAEzBt/TzFfXLktmWjFNugGDWl8coKX4= +cloud.google.com/go/beyondcorp v1.0.10/go.mod h1:G09WxvxJASbxbrzaJUMVvNsB1ZiaKxpbtkjiFtpDtbo= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.62.0/go.mod h1:5ee+ZkF1x/ntgCsFQJAQTM3QkAZOecfCmvxhkJsWRSA= +cloud.google.com/go/bigtable v1.18.1/go.mod h1:NAVyfJot9jlo+KmgWLUJ5DJGwNDoChzAcrecLpmuAmY= +cloud.google.com/go/bigtable v1.20.0/go.mod h1:upJDn8frsjzpRMfybiWkD1PG6WCCL7CRl26MgVeoXY4= +cloud.google.com/go/bigtable v1.27.2-0.20240802230159-f371928b558f/go.mod h1:avmXcmxVbLJAo9moICRYMgDyTTPoV0MA0lHKnyqV4fQ= +cloud.google.com/go/billing v1.18.9/go.mod h1:bKTnh8MBfCMUT1fzZ936CPN9rZG7ZEiHB2J3SjIjByc= +cloud.google.com/go/binaryauthorization v1.8.7/go.mod h1:cRj4teQhOme5SbWQa96vTDATQdMftdT5324BznxANtg= +cloud.google.com/go/certificatemanager v1.8.5/go.mod h1:r2xINtJ/4xSz85VsqvjY53qdlrdCjyniib9Jp98ZKKM= +cloud.google.com/go/channel v1.17.11/go.mod h1:gjWCDBcTGQce/BSMoe2lAqhlq0dIRiZuktvBKXUawp0= +cloud.google.com/go/cloudbuild v1.16.5/go.mod h1:HXLpZ8QeYZgmDIWpbl9Gs22p6o6uScgQ/cV9HF9cIZU= +cloud.google.com/go/clouddms v1.7.10/go.mod h1:PzHELq0QDyA7VaD9z6mzh2mxeBz4kM6oDe8YxMxd4RA= +cloud.google.com/go/cloudtasks v1.12.12/go.mod h1:8UmM+duMrQpzzRREo0i3x3TrFjsgI/3FQw3664/JblA= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= +cloud.google.com/go/compute v1.27.4/go.mod h1:7JZS+h21ERAGHOy5qb7+EPyXlQwzshzrx1x6L9JhTqU= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/contactcenterinsights v1.13.6/go.mod h1:mL+DbN3pMQGaAbDC4wZhryLciwSwHf5Tfk4Itr72Zyk= +cloud.google.com/go/container v1.38.0/go.mod h1:U0uPBvkVWOJGY/0qTVuPS7NeafFEUsHSPqT5pB8+fCY= +cloud.google.com/go/containeranalysis v0.12.1/go.mod h1:+/lcJIQSFt45TC0N9Nq7/dPbl0isk6hnC4EvBBqyXsM= +cloud.google.com/go/datacatalog v1.20.3/go.mod h1:AKC6vAy5urnMg5eJK3oUjy8oa5zMbiY33h125l8lmlo= +cloud.google.com/go/datacatalog v1.21.0/go.mod h1:DB0QWF9nelpsbB0eR/tA0xbHZZMvpoFD1XFy3Qv/McI= +cloud.google.com/go/dataflow v0.9.11/go.mod h1:CCLufd7I4pPfyp54qMgil/volrL2ZKYjXeYLfQmBGJs= +cloud.google.com/go/dataform v0.9.8/go.mod h1:cGJdyVdunN7tkeXHPNosuMzmryx55mp6cInYBgxN3oA= +cloud.google.com/go/datafusion v1.7.11/go.mod h1:aU9zoBHgYmoPp4dzccgm/Gi4xWDMXodSZlNZ4WNeptw= +cloud.google.com/go/datalabeling v0.8.11/go.mod h1:6IGUV3z7hlkAU5ndKVshv/8z+7pxE+k0qXsEjyzO1Xg= +cloud.google.com/go/dataplex v1.18.2/go.mod h1:NuBpJJMGGQn2xctX+foHEDKRbizwuiHJamKvvSteY3Q= +cloud.google.com/go/dataproc/v2 v2.5.3/go.mod h1:RgA5QR7v++3xfP7DlgY3DUmoDSTaaemPe0ayKrQfyeg= +cloud.google.com/go/dataqna v0.8.11/go.mod h1:74Icl1oFKKZXPd+W7YDtqJLa+VwLV6wZ+UF+sHo2QZQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.17.1/go.mod h1:mtzZ2HcVtz90OVrEXXGDc2pO4NM1kiBQy8YV4qGe0ZM= +cloud.google.com/go/datastream v1.10.10/go.mod h1:NqchuNjhPlISvWbk426/AU/S+Kgv7srlID9P5XOAbtg= +cloud.google.com/go/deploy v1.21.0/go.mod h1:PaOfS47VrvmYnxG5vhHg0KU60cKeWcqyLbMBjxS8DW8= +cloud.google.com/go/dialogflow v1.55.0/go.mod h1:0u0hSlJiFpMkMpMNoFrQETwDjaRm8Q8hYKv+jz5JeRA= +cloud.google.com/go/dlp v1.16.0/go.mod h1:LtPZxZAenBXKzvWIOB2hdHIXuEcK0wW0En8//u+/nNA= +cloud.google.com/go/documentai v1.31.0/go.mod h1:5ajlDvaPyl9tc+K/jZE8WtYIqSXqAD33Z1YAYIjfad4= +cloud.google.com/go/domains v0.9.11/go.mod h1:efo5552kUyxsXEz30+RaoIS2lR7tp3M/rhiYtKXkhkk= +cloud.google.com/go/edgecontainer v1.2.5/go.mod h1:OAb6tElD3F3oBujFAup14PKOs9B/lYobTb6LARmoACY= +cloud.google.com/go/errorreporting v0.3.1/go.mod h1:6xVQXU1UuntfAf+bVkFk6nld41+CPyF2NSPCyXE3Ztk= +cloud.google.com/go/essentialcontacts v1.6.12/go.mod h1:UGhWTIYewH8Ma4wDRJp8cMAHUCeAOCKsuwd6GLmmQLc= +cloud.google.com/go/eventarc v1.13.10/go.mod h1:KlCcOMApmUaqOEZUpZRVH+p0nnnsY1HaJB26U4X5KXE= +cloud.google.com/go/filestore v1.8.7/go.mod h1:dKfyH0YdPAKdYHqAR/bxZeil85Y5QmrEVQwIYuRjcXI= +cloud.google.com/go/firestore v1.16.0/go.mod h1:+22v/7p+WNBSQwdSwP57vz47aZiY+HrDkrOsJNhk7rg= +cloud.google.com/go/functions v1.16.6/go.mod h1:wOzZakhMueNQaBUJdf0yjsJIe0GBRu+ZTvdSTzqHLs0= +cloud.google.com/go/gkebackup v1.5.4/go.mod h1:V+llvHlRD0bCyrkYaAMJX+CHralceQcaOWjNQs8/Ymw= +cloud.google.com/go/gkeconnect v0.8.11/go.mod h1:ejHv5ehbceIglu1GsMwlH0nZpTftjxEY6DX7tvaM8gA= +cloud.google.com/go/gkehub v0.14.11/go.mod h1:CsmDJ4qbBnSPkoBltEubK6qGOjG0xNfeeT5jI5gCnRQ= +cloud.google.com/go/gkemulticloud v1.2.4/go.mod h1:PjTtoKLQpIRztrL+eKQw8030/S4c7rx/WvHydDJlpGE= +cloud.google.com/go/grafeas v0.3.6/go.mod h1:to6ECAPgRO2xeqD8ISXHc70nObJuaKZThreQOjeOH3o= +cloud.google.com/go/gsuiteaddons v1.6.11/go.mod h1:U7mk5PLBzDpHhgHv5aJkuvLp9RQzZFpa8hgWAB+xVIk= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/iam v1.1.7/go.mod h1:J4PMPg8TtyurAUvSmPj8FF3EDgY1SPRZxcUGrn7WXGA= +cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= +cloud.google.com/go/iam v1.1.10/go.mod h1:iEgMq62sg8zx446GCaijmA2Miwg5o3UbO+nI47WHJps= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= +cloud.google.com/go/iam v1.1.12/go.mod h1:9LDX8J7dN5YRyzVHxwQzrQs9opFFqn0Mxs9nAeB+Hhg= +cloud.google.com/go/iap v1.9.10/go.mod h1:pO0FEirrhMOT1H0WVwpD5dD9r3oBhvsunyBQtNXzzc0= +cloud.google.com/go/ids v1.4.11/go.mod h1:+ZKqWELpJm8WcRRsSvKZWUdkriu4A3XsLLzToTv3418= +cloud.google.com/go/iot v1.7.11/go.mod h1:0vZJOqFy9kVLbUXwTP95e0dWHakfR4u5IWqsKMGIfHk= +cloud.google.com/go/kms v1.15.8/go.mod h1:WoUHcDjD9pluCg7pNds131awnH429QGvRM3N/4MyoVs= +cloud.google.com/go/kms v1.18.2/go.mod h1:YFz1LYrnGsXARuRePL729oINmN5J/5e7nYijgvfiIeY= +cloud.google.com/go/kms v1.18.4/go.mod h1:SG1bgQ3UWW6/KdPo9uuJnzELXY5YTTMJtDYvajiQ22g= +cloud.google.com/go/language v1.13.0/go.mod h1:B9FbD17g1EkilctNGUDAdSrBHiFOlKNErLljO7jplDU= +cloud.google.com/go/lifesciences v0.9.11/go.mod h1:NMxu++FYdv55TxOBEvLIhiAvah8acQwXsz79i9l9/RY= +cloud.google.com/go/logging v1.11.0/go.mod h1:5LDiJC/RxTt+fHc1LAt20R9TKiUTReDg6RuuFOZ67+A= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= +cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= +cloud.google.com/go/longrunning v0.5.2/go.mod h1:nqo6DQbNV2pXhGDbDMoN2bWz68MjZUzqv2YttZiveCs= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= +cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= +cloud.google.com/go/longrunning v0.5.9/go.mod h1:HD+0l9/OOW0za6UWdKJtXoFAX/BGg/3Wj8p10NeWF7c= +cloud.google.com/go/longrunning v0.5.10/go.mod h1:tljz5guTr5oc/qhlUjBlk7UAIFMOGuPNxkNDZXlLics= +cloud.google.com/go/longrunning v0.5.11/go.mod h1:rDn7//lmlfWV1Dx6IB4RatCPenTwwmqXuiP0/RgoEO4= +cloud.google.com/go/managedidentities v1.6.11/go.mod h1:df+8oZ1D4Eri+NrcpuiR5Hd6MGgiMqn0ZCzNmBYPS0A= +cloud.google.com/go/maps v1.11.6/go.mod h1:MOS/NN0L6b7Kumr8bLux9XTpd8+D54DYxBMUjq+XfXs= +cloud.google.com/go/mediatranslation v0.8.11/go.mod h1:3sNEm0fx61eHk7rfzBzrljVV9XKr931xI3OFacQBVFg= +cloud.google.com/go/memcache v1.10.11/go.mod h1:ubJ7Gfz/xQawQY5WO5pht4Q0dhzXBFeEszAeEJnwBHU= +cloud.google.com/go/metastore v1.13.10/go.mod h1:RPhMnBxUmTLT1fN7fNbPqtH5EoGHueDxubmJ1R1yT84= +cloud.google.com/go/monitoring v1.20.2/go.mod h1:36rpg/7fdQ7NX5pG5x1FA7cXTVXusOp6Zg9r9e1+oek= +cloud.google.com/go/monitoring v1.20.3/go.mod h1:GPIVIdNznIdGqEjtRKQWTLcUeRnPjZW85szouimiczU= +cloud.google.com/go/networkconnectivity v1.14.10/go.mod h1:f7ZbGl4CV08DDb7lw+NmMXQTKKjMhgCEEwFbEukWuOY= +cloud.google.com/go/networkmanagement v1.13.6/go.mod h1:WXBijOnX90IFb6sberjnGrVtZbgDNcPDUYOlGXmG8+4= +cloud.google.com/go/networksecurity v0.9.11/go.mod h1:4xbpOqCwplmFgymAjPFM6ZIplVC6+eQ4m7sIiEq9oJA= +cloud.google.com/go/notebooks v1.11.9/go.mod h1:JmnRX0eLgHRJiyxw8HOgumW9iRajImZxr7r75U16uXw= +cloud.google.com/go/optimization v1.6.9/go.mod h1:mcvkDy0p4s5k7iSaiKrwwpN0IkteHhGmuW5rP9nXA5M= +cloud.google.com/go/orchestration v1.9.6/go.mod h1:gQvdIsHESZJigimnbUA8XLbYeFlSg/z+A7ppds5JULg= +cloud.google.com/go/orgpolicy v1.12.5/go.mod h1:f778/jOHKp6cP6NbbQgjy4SDfQf6BoVGiSWdxky3ONQ= +cloud.google.com/go/orgpolicy v1.12.7/go.mod h1:Os3GlUFRPf1UxOHTup5b70BARnhHeQNNVNZzJXPbWYI= +cloud.google.com/go/osconfig v1.13.0/go.mod h1:tlACnQi1rtSLnHRYzfw9SH9zXs0M7S1jqiW2EOCn2Y0= +cloud.google.com/go/osconfig v1.13.2/go.mod h1:eupylkWQJCwSIEMkpVR4LqpgKkQi0mD4m1DzNCgpQso= +cloud.google.com/go/oslogin v1.13.7/go.mod h1:xq027cL0fojpcEcpEQdWayiDn8tIx3WEFYMM6+q7U+E= +cloud.google.com/go/phishingprotection v0.8.11/go.mod h1:Mge0cylqVFs+D0EyxlsTOJ1Guf3qDgrztHzxZqkhRQM= +cloud.google.com/go/policytroubleshooter v1.10.9/go.mod h1:X8HEPVBWz8E+qwI/QXnhBLahEHdcuPO3M9YvSj0LDek= +cloud.google.com/go/privatecatalog v0.9.11/go.mod h1:awEF2a8M6UgoqVJcF/MthkF8SSo6OoWQ7TtPNxUlljY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.38.0/go.mod h1:IPMJSWSus/cu57UyR01Jqa/bNOQA+XnPF6Z4dKW4fAA= +cloud.google.com/go/pubsub v1.41.0/go.mod h1:g+YzC6w/3N91tzG66e2BZtp7WrpBBMXVa3Y9zVoOGpk= +cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= +cloud.google.com/go/recaptchaenterprise/v2 v2.14.2/go.mod h1:MwPgdgvBkE46aWuuXeBTCB8hQJ88p+CpXInROZYCTkc= +cloud.google.com/go/recommendationengine v0.8.11/go.mod h1:cEkU4tCXAF88a4boMFZym7U7uyxvVwcQtKzS85IbQio= +cloud.google.com/go/recommender v1.12.7/go.mod h1:lG8DVtczLltWuaCv4IVpNphONZTzaCC9KdxLYeZM5G4= +cloud.google.com/go/redis v1.16.4/go.mod h1:unCVfLP5eFrVhGLDnb7IaSaWxuZ+7cBgwwBwbdG9m9w= +cloud.google.com/go/resourcemanager v1.9.11/go.mod h1:SbNAbjVLoi2rt9G74bEYb3aw1iwvyWPOJMnij4SsmHA= +cloud.google.com/go/resourcesettings v1.7.4/go.mod h1:seBdLuyeq+ol2u9G2+74GkSjQaxaBWF+vVb6mVzQFG0= +cloud.google.com/go/retail v1.17.4/go.mod h1:oPkL1FzW7D+v/hX5alYIx52ro2FY/WPAviwR1kZZTMs= +cloud.google.com/go/run v1.4.0/go.mod h1:4G9iHLjdOC+CQ0CzA0+6nLeR6NezVPmlj+GULmb0zE4= +cloud.google.com/go/scheduler v1.10.12/go.mod h1:6DRtOddMWJ001HJ6MS148rtLSh/S2oqd2hQC3n5n9fQ= +cloud.google.com/go/secretmanager v1.13.5/go.mod h1:/OeZ88l5Z6nBVilV0SXgv6XJ243KP2aIhSWRMrbvDCQ= +cloud.google.com/go/security v1.17.4/go.mod h1:KMuDJH+sEB3KTODd/tLJ7kZK+u2PQt+Cfu0oAxzIhgo= +cloud.google.com/go/securitycenter v1.33.1/go.mod h1:jeFisdYUWHr+ig72T4g0dnNCFhRwgwGoQV6GFuEwafw= +cloud.google.com/go/servicedirectory v1.11.11/go.mod h1:pnynaftaj9LmRLIc6t3r7r7rdCZZKKxui/HaF/RqYfs= +cloud.google.com/go/shell v1.7.11/go.mod h1:SywZHWac7onifaT9m9MmegYp3GgCLm+tgk+w2lXK8vg= +cloud.google.com/go/spanner v1.65.0/go.mod h1:dQGB+w5a67gtyE3qSKPPxzniedrnAmV6tewQeBY7Hxs= +cloud.google.com/go/speech v1.24.0/go.mod h1:HcVyIh5jRXM5zDMcbFCW+DF2uK/MSGN6Rastt6bj1ic= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= +cloud.google.com/go/storage v1.39.1/go.mod h1:xK6xZmxZmo+fyP7+DEF6FhNc24/JAe95OLyOHCXFH1o= +cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= +cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= +cloud.google.com/go/storage v1.42.0/go.mod h1:HjMXRFq65pGKFn6hxj6x3HCyR41uSB72Z0SO/Vn6JFQ= +cloud.google.com/go/storagetransfer v1.10.10/go.mod h1:8+nX+WgQ2ZJJnK8e+RbK/zCXk8T7HdwyQAJeY7cEcm0= +cloud.google.com/go/talent v1.6.12/go.mod h1:nT9kNVuJhZX2QgqKZS6t6eCWZs5XEBYRBv6bIMnPmo4= +cloud.google.com/go/texttospeech v1.7.11/go.mod h1:Ua125HU+WT2IkIo5MzQtuNpNEk72soShJQVdorZ1SAE= +cloud.google.com/go/tpu v1.6.11/go.mod h1:W0C4xaSj1Ay3VX/H96FRvLt2HDs0CgdRPVI4e7PoCDk= +cloud.google.com/go/trace v1.10.11/go.mod h1:fUr5L3wSXerNfT0f1bBg08W4axS2VbHGgYcfH4KuTXU= +cloud.google.com/go/translate v1.10.7/go.mod h1:mH/+8tvcItuy1cOWqU+/Y3iFHgkVUObNIQYI/kiFFiY= +cloud.google.com/go/video v1.22.0/go.mod h1:CxPshUNAb1ucnzbtruEHlAal9XY+SPG2cFqC/woJzII= +cloud.google.com/go/videointelligence v1.11.11/go.mod h1:dab2Ca3AXT6vNJmt3/6ieuquYRckpsActDekLcsd6dU= +cloud.google.com/go/vision/v2 v2.8.6/go.mod h1:G3v0uovxCye3u369JfrHGY43H6u/IQ08x9dw5aVH8yY= +cloud.google.com/go/vmmigration v1.7.11/go.mod h1:PmD1fDB0TEHGQR1tDZt9GEXFB9mnKKalLcTVRJKzcQA= +cloud.google.com/go/vmwareengine v1.2.0/go.mod h1:rPjCHu6hG9N8d6PhkoDWFkqL9xpbFY+ueVW+0pNFbZg= +cloud.google.com/go/vpcaccess v1.7.11/go.mod h1:a2cuAiSCI4TVK0Dt6/dRjf22qQvfY+podxst2VvAkcI= +cloud.google.com/go/webrisk v1.9.11/go.mod h1:mK6M8KEO0ZI7VkrjCq3Tjzw4vYq+3c4DzlMUDVaiswE= +cloud.google.com/go/websecurityscanner v1.6.11/go.mod h1:vhAZjksELSg58EZfUQ1BMExD+hxqpn0G0DuyCZQjiTg= +cloud.google.com/go/workflows v1.12.10/go.mod h1:RcKqCiOmKs8wFUEf3EwWZPH5eHc7Oq0kamIyOUCk0IE= code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4= code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a h1:3i+FJ7IpSZHL+VAjtpQeZCRhrpP0odl5XfoLBY4fxJ8= git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a/go.mod h1:C7hXLmFmPYPjIDGfQl1clsmQ5TMEQfmzWTrJk475bUs= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/42wim/httpsig v1.2.2 h1:ofAYoHUNs/MJOLqQ8hIxeyz2QxOz8qdSVvp3PX/oPgA= github.com/42wim/httpsig v1.2.2/go.mod h1:P/UYo7ytNBFwc+dg35IubuAUIs8zj5zzFIgUCEl55WY= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= @@ -60,8 +301,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuo github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= @@ -72,6 +313,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= +github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= @@ -101,8 +344,14 @@ github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg= github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/akrylysov/pogreb v0.10.2 h1:e6PxmeyEhWyi2AKOBIJzAEi4HkiC+lKyCocRGlnDi78= github.com/akrylysov/pogreb v0.10.2/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI= +github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= +github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= @@ -112,6 +361,9 @@ github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4E github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmEU+AT+Olodb+WoN2Y= +github.com/alecthomas/participle/v2 v2.1.0/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c= +github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -126,6 +378,7 @@ github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7V github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs= github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 h1:8PmGpDEZl9yDpcdEr6Odf23feCxK3LNUNMxjXg41pZQ= github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= @@ -141,6 +394,9 @@ github.com/antchfx/xmlquery v1.4.4/go.mod h1:AEPEEPYE9GnA2mj5Ur2L5Q5/2PycJ0N9Fus github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antchfx/xpath v1.3.4 h1:1ixrW1VnXd4HurCj7qnqnR0jo14g8JMe20Fshg1Vgz4= github.com/antchfx/xpath v1.3.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA= +github.com/apache/thrift v0.17.0/go.mod h1:OLxhMRJxomX+1I/KUw03qoV3mMz16BwaKI+d4fPBx7Q= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= @@ -209,6 +465,8 @@ github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc= github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -226,6 +484,8 @@ github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -255,10 +515,13 @@ github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0V github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= @@ -272,10 +535,39 @@ github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCy github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ= github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= @@ -290,6 +582,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c h1:+Zo5Ca9GH0RoeVZQKzFJcTLoAixx5s5Gq3pTIS+n354= github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c/go.mod h1:HJGU9ULdREjOcVGZVPB5s6zYmHi1RxzT71l2wQyLmnE= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= @@ -297,16 +591,20 @@ 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/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -314,13 +612,39 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= +github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -338,6 +662,7 @@ github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9 github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= @@ -350,6 +675,11 @@ github.com/go-echarts/go-echarts/v2 v2.6.0 h1:4wEquGT/I7lipHnOCh/z3qa8E4dY0SYFdE github.com/go-echarts/go-echarts/v2 v2.6.0/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= @@ -366,26 +696,43 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU= github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pg/pg v8.0.7+incompatible h1:ty/sXL1OZLo+47KK9N8llRcmbA9tZasqbQ/OO4ld53g= github.com/go-pg/pg v8.0.7+incompatible/go.mod h1:a2oXow+aFOrvwcKs3eIA0lNFmMilrxK2sOkB5NWe0vA= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA= @@ -408,8 +755,11 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.9.8/go.mod h1:JubOolP3gh0HpiBc4BLRD4YmjEjHAmIIB2aaXKkTfoE= +github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -423,7 +773,12 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -437,6 +792,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -452,15 +809,20 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -469,9 +831,11 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -482,12 +846,17 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo= github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8= github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= +github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -495,24 +864,81 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= +github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/cloud-bigtable-clients-test v0.0.0-20221104150409-300c96f7b1f5/go.mod h1:Udm7et5Lt9Xtzd4n07/kKP80IdlR4zVDjtlUZEO2Dd8= +github.com/googleapis/cloud-bigtable-clients-test v0.0.0-20230505150253-16eeee810d3a/go.mod h1:2n/InOx7Q1jaqXZJ0poJmsZxb6K+OfHEbhA/+LPJrII= +github.com/googleapis/cloud-bigtable-clients-test v0.0.2/go.mod h1:mk3CrkrouRgtnhID6UZQDK3DrFFa7cYCAJcEmNsHYrY= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/hamba/avro/v2 v2.17.2/go.mod h1:Q9YK+qxAhtVrNqOhwlZTATLgLA8qxG2vtvkhK8fJ7Jo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -540,7 +966,11 @@ github.com/hdm/jarm-go v0.0.7/go.mod h1:kinGoS0+Sdn1Rr54OtanET5E5n7AlD6T6CrJAKDj github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= @@ -587,8 +1017,11 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ= github.com/kataras/jwt v0.1.10/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= @@ -597,12 +1030,15 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kitabisa/go-ci v1.0.3 h1:JmIUIvcercRQc/9x/v02ydCCqU4MadSHaNaOF8T2pGA= github.com/kitabisa/go-ci v1.0.3/go.mod h1:e3wBSzaJbcifXrr/Gw2ZBLn44MmeqP5WySwXyHlCK/U= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= @@ -610,6 +1046,7 @@ github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -626,6 +1063,7 @@ github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa h1:KQKuQDgA3DZX6C396lt3WDYB9Um1gLITLbvficVbqXk= @@ -642,19 +1080,34 @@ github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuM github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d h1:vFzYZc8yji+9DmNRhpEbs8VBK4CgV/DPfGzeVJSSp/8= +github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs= github.com/mackerelio/go-osstat v0.2.4/go.mod h1:Zy+qzGdZs3A9cuIqmgbJvwbmLQH9dJvtio5ZjJTbdlQ= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -672,6 +1125,8 @@ github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= github.com/minio/minlz v1.0.0 h1:Kj7aJZ1//LlTP1DM8Jm7lNKvvJS2m74gyyXXn3+uJWQ= github.com/minio/minlz v1.0.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= @@ -680,12 +1135,23 @@ github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7/go.mod h1:bO02G github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= -github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= +github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= +github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -697,6 +1163,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= @@ -729,8 +1197,8 @@ github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeD github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/opencontainers/runc v1.2.3 h1:fxE7amCzfZflJO2lHXf4y/y8M1BoAqp+FVmG19oYB80= github.com/opencontainers/runc v1.2.3/go.mod h1:nSxcWUydXrsBZVYNSkTjoQ/N6rcyTtn+1SD5D4+kRIM= github.com/openrdap/rdap v0.9.1 h1:Rv6YbanbiVPsKRvOLdUmlU1AL5+2OFuEFLjFN+mQsCM= @@ -742,21 +1210,28 @@ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/praetorian-inc/fingerprintx v1.1.15 h1:CVIxrIQARbmdk5h8E9tIJZbvFoY2sGLLG9rpFVfQqpA= github.com/praetorian-inc/fingerprintx v1.1.15/go.mod h1:hqRroITBwKpP8BOGF+n/A+qv9wSF7OSVinmu5NCyOUI= github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kID2iwsDqI= @@ -840,6 +1315,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -859,15 +1336,21 @@ github.com/refraction-networking/utls v1.7.1 h1:dxg+jla3uocgN8HtX+ccwDr68uCBBO3q github.com/refraction-networking/utls v1.7.1/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ= 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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= @@ -883,6 +1366,8 @@ github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKl github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= +github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM= +github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -909,26 +1394,43 @@ github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBD github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/substrait-io/substrait-go v0.4.2/go.mod h1:qhpnLmrcvAnlZsUyPXZRqldiHapPTXC3t7xFgDi3aQg= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 h1:GXIyLuIJ5Qk46lI8WJ83qHBZKUI3zhmMmuoY9HICUIQ= github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9/go.mod h1:uQdBQGrE1fZ2EyOs0pLcCDd1bBV4rSThieuIIGhXZ50= +github.com/testcontainers/testcontainers-go v0.38.0 h1:d7uEapLcv2P8AvH8ahLqDMMxda2W9gQN1nRbHS28HBw= +github.com/testcontainers/testcontainers-go v0.38.0/go.mod h1:C52c9MoHpWO+C4aqmgSU+hxlR5jlEayWtgYrb8Pzz1w= +github.com/testcontainers/testcontainers-go/modules/mongodb v0.37.0 h1:drGy4LJOVkIKpKGm1YKTfVzb1qRhN/konVpmuUphq0k= +github.com/testcontainers/testcontainers-go/modules/mongodb v0.37.0/go.mod h1:e9/4dGJfSZW59/kXGf/ksrEvA+BqP/daax0Usp2cpsM= github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI= github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= @@ -936,6 +1438,7 @@ github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EU github.com/tidwall/buntdb v1.3.1 h1:HKoDF01/aBhl9RjYtbaLnvX9/OuenwvQiC3OP1CcL4o= github.com/tidwall/buntdb v1.3.1/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg= @@ -949,14 +1452,15 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/rtred v0.1.2 h1:exmoQtOLvDoO8ud++6LwVsAMTu0KPzLTUrMln8u1yu8= github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaymYE= github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw= github.com/tim-ywliu/nested-logrus-formatter v1.3.2 h1:jugNJ2/CNCI79SxOJCOhwUHeN3O7/7/bj+ZRGOFlCSw= github.com/tim-ywliu/nested-logrus-formatter v1.3.2/go.mod h1:oGPmcxZB65j9Wo7mCnQKSrKEJtVDqyjD666SGmyStXI= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -1028,6 +1532,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= @@ -1038,12 +1544,14 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zcalusic/sysinfo v1.0.2 h1:nwTTo2a+WQ0NXwo0BGRojOJvJ/5XKvQih+2RrtWqfxc= github.com/zcalusic/sysinfo v1.0.2/go.mod h1:kluzTYflRWo6/tXVMJPdEjShsbPpsFRyy+p1mBQPC30= -github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 h1:Nzukz5fNOBIHOsnP+6I79kPx3QhLv8nBy2mfFhBRq30= github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= @@ -1060,6 +1568,7 @@ github.com/zmap/zgrab2 v0.1.8/go.mod h1:5d8HSmUwvllx4q1qG50v/KXphkg45ZzWdaQtgTFn github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8= gitlab.com/gitlab-org/api/client-go v0.130.1 h1:1xF5C5Zq3sFeNg3PzS2z63oqrxifne3n/OnbI7nptRc= gitlab.com/gitlab-org/api/client-go v0.130.1/go.mod h1:ZhSxLAWadqP6J9lMh40IAZOlOxBLPRh7yFOXR/bMJWM= +go.einride.tech/aip v0.67.1/go.mod h1:ZGX4/zKw8dcgzdLsrvpOOGxfxI2QSk12SlP7d6c0/XI= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= @@ -1069,6 +1578,56 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -1087,41 +1646,75 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1130,6 +1723,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1138,19 +1733,30 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1178,34 +1784,99 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= +golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1218,15 +1889,20 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1248,6 +1924,7 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1262,78 +1939,154 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1346,6 +2099,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1374,17 +2128,50 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1401,6 +2188,73 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= +google.golang.org/api v0.121.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= +google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +google.golang.org/api v0.148.0/go.mod h1:8/TBgwaKjfqTdacOJrOv2+2Q6fBDU1uHKK06oGSkxzU= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +google.golang.org/api v0.150.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg= +google.golang.org/api v0.155.0/go.mod h1:GI5qK5f40kCpHfPn6+YzGAByIKWv8ujFnmoWm7Igduk= +google.golang.org/api v0.160.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= +google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= +google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.170.0/go.mod h1:/xql9M2btF85xac/VAm4PsLMTLVGUOpq4BE9R8jyNy8= +google.golang.org/api v0.176.1/go.mod h1:j2MaSDYcvYV1lkZ1+SMW4IeF90SrEyFA+tluDYWRrFg= +google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw= +google.golang.org/api v0.178.0/go.mod h1:84/k2v8DFpDRebpGcooklv/lais3MEfqpaBLA12gl2U= +google.golang.org/api v0.180.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE= +google.golang.org/api v0.182.0/go.mod h1:cGhjy4caqA5yXRzEhkHI8Y9mfyC2VLTlER2l08xaqtM= +google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= +google.golang.org/api v0.184.0/go.mod h1:CeDTtUEiYENAf8PPG5VZW2yNp2VM3VWbCeTioAZBTBA= +google.golang.org/api v0.186.0/go.mod h1:hvRbBmgoje49RV3xqVXrmP6w93n6ehGgIVPYrGtBFFc= +google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= +google.golang.org/api v0.189.0/go.mod h1:FLWGJKb0hb+pU2j+rJqwbnsF+ym+fQs73rbJ+KAUgy8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1408,35 +2262,32 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22duwci1+TG7bg2/L1LQsXwfjPlmuJA0= +google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:+34luvCflYKiKylNwGJfn9cFBbcL/WrkciMmDmsTQ/A= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20231212172506-995d672761c0/go.mod h1:guYXGPwC6jwxgWKW5Y405fKWOFNwlvUlUnzyp9i0uqo= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:ZSvZ8l+AWJwXw91DoTjWjaVLpWU6o0eZ4YLYpH8aLeQ= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:SCz6T5xjNXM4QFPRwxHcfChp7V+9DcXR3ay2TkHR8Tg= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240205150955-31a09d347014/go.mod h1:EhZbXt+eY4Yr3YVaEGLdNZF5viWowOJZ8KTPqjYMKzg= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:om8Bj876Z0v9ei+RD1LnEWig7vpHQ371PUqsgjmLQEA= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:vh/N7795ftP0AkN1w8XKqN4w1OdUKXW5Eummda+ofv8= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240311132316-a219d84964c2/go.mod h1:vh/N7795ftP0AkN1w8XKqN4w1OdUKXW5Eummda+ofv8= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:IN9OQUXZ0xT+26MDwZL8fJcYw+y99b0eYPA2U15Jt8o= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240429193739-8cf5692501f6/go.mod h1:ULqtoQMxDLNRfW+pJbKA68wtIy1OiYjdIsJs3PMpzh8= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240521202816-d264139d666e/go.mod h1:0J6mmn3XAEjfNbPvpH63c0RXCjGNFcCzlEfWSN4In+k= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240528184218-531527333157/go.mod h1:0J6mmn3XAEjfNbPvpH63c0RXCjGNFcCzlEfWSN4In+k= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240604185151-ef581f913117/go.mod h1:0J6mmn3XAEjfNbPvpH63c0RXCjGNFcCzlEfWSN4In+k= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240617180043-68d350f18fd4/go.mod h1:/oe3+SiHAwz6s+M25PyTygWm3lnrhmGqIuIfkoUocqk= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:/oe3+SiHAwz6s+M25PyTygWm3lnrhmGqIuIfkoUocqk= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240708141625-4ad9e859172b/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240722135656-d784300faade/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1449,6 +2300,56 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= +google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1456,15 +2357,20 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= @@ -1488,6 +2394,7 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1496,8 +2403,9 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1505,11 +2413,44 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0= mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY= +modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= +modernc.org/cc/v3 v3.38.1/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI= +modernc.org/ccgo/v3 v3.0.0-20220910160915-348f15de615a/go.mod h1:8p47QxPkdugex9J4n9P2tLZ9bK01yngIVp00g4nomW0= +modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA= +modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0= +modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= +modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= +modernc.org/libc v1.21.2/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI= +modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI= +modernc.org/libc v1.22.4/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.21.2/go.mod h1:cxbLkB5WS32DnQqeH4h4o1B0eMr8W/y8/RGuxQ3JsC0= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.1/go.mod h1:aEjeGJX2gz1oWKOLDVZ2tnEWLUrIn8H+GFu+akoDhqs= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ= moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From d76187f99a1fb345f9bdada5d6c44ab274c1fdcc Mon Sep 17 00:00:00 2001 From: cui Date: Thu, 28 Aug 2025 01:01:04 +0800 Subject: [PATCH 103/135] Refactor to use reflect.TypeFor (#6428) --- pkg/js/gojs/gojs.go | 2 +- pkg/js/gojs/set.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/js/gojs/gojs.go b/pkg/js/gojs/gojs.go index e82dcb6f3..f24413efb 100644 --- a/pkg/js/gojs/gojs.go +++ b/pkg/js/gojs/gojs.go @@ -59,7 +59,7 @@ func wrapModuleFunc(runtime *goja.Runtime, fn interface{}) interface{} { } // Only wrap if first parameter is context.Context - if fnType.NumIn() == 0 || fnType.In(0) != reflect.TypeOf((*context.Context)(nil)).Elem() { + if fnType.NumIn() == 0 || fnType.In(0) != reflect.TypeFor[context.Context]() { return fn // Return original function unchanged if it doesn't have context.Context as first arg } diff --git a/pkg/js/gojs/set.go b/pkg/js/gojs/set.go index 4d4407def..aa1afd79b 100644 --- a/pkg/js/gojs/set.go +++ b/pkg/js/gojs/set.go @@ -34,7 +34,7 @@ func wrapWithContext(runtime *goja.Runtime, fn interface{}) interface{} { } // Only wrap if first parameter is context.Context - if fnType.NumIn() == 0 || fnType.In(0) != reflect.TypeOf((*context.Context)(nil)).Elem() { + if fnType.NumIn() == 0 || fnType.In(0) != reflect.TypeFor[context.Context]() { return fn // Return original function unchanged if it doesn't have context.Context as first arg } From af7b2f166efbf04c2a643c54f9a6184d45c30400 Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Sun, 31 Aug 2025 03:10:51 +0530 Subject: [PATCH 104/135] issue / discussion template update --- .github/DISCUSSION_TEMPLATE.md | 76 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 20 +++-- .../reference-templates/README.md | 45 +++++++++++ .../bug-report-reference.yml} | 0 .../feature-request-reference.yml} | 0 5 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 .github/DISCUSSION_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/reference-templates/README.md rename .github/ISSUE_TEMPLATE/{bug-report.yml => reference-templates/bug-report-reference.yml} (100%) rename .github/ISSUE_TEMPLATE/{feature-request.yml => reference-templates/feature-request-reference.yml} (100%) diff --git a/.github/DISCUSSION_TEMPLATE.md b/.github/DISCUSSION_TEMPLATE.md new file mode 100644 index 000000000..4c1367265 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE.md @@ -0,0 +1,76 @@ +# Nuclei Discussion Guidelines + +## Before Creating a Discussion + +1. **Search existing discussions and issues** to avoid duplicates +2. **Check the documentation** and README first +3. **Browse the FAQ** and common questions + +## Bug Reports in Discussions + +When reporting a bug in [Q&A Discussions](https://github.com/projectdiscovery/nuclei/discussions/categories/q-a), please include: + +### Required Information: +- **Clear title** with `[BUG]` prefix (e.g., "[BUG] Nuclei crashes when...") +- **Current behavior** - What's happening now? +- **Expected behavior** - What should happen instead? +- **Steps to reproduce** - Commands or actions that trigger the issue +- **Environment details**: + - OS and version + - Nuclei version (`nuclei -version`) + - Go version (if installed via `go install`) +- **Log output** - Run with `-verbose` or `-debug` for detailed logs +- **Redact sensitive information** - Remove target URLs, credentials, etc. + +### After Discussion: +- Maintainers will review and validate the bug report +- Valid bugs will be converted to issues with proper labels and tracking +- Questions and misconfigurations will be resolved in the discussion + +## Feature Requests in Discussions + +When requesting a feature in [Ideas Discussions](https://github.com/projectdiscovery/nuclei/discussions/categories/ideas), please include: + +### Required Information: +- **Clear title** with `[FEATURE]` prefix (e.g., "[FEATURE] Add support for...") +- **Feature description** - What do you want to be added? +- **Use case** - Why is this feature needed? What problem does it solve? +- **Implementation ideas** - If you have suggestions on how it could work +- **Alternatives considered** - What other solutions have you thought about? + +### After Discussion: +- Community and maintainers will discuss the feasibility +- Popular and viable features will be converted to issues +- Similar features may be grouped together +- Rejected features will be explained in the discussion + +## Getting Help + +For general questions, troubleshooting, and "how-to" topics: +- Use [Q&A Discussions](https://github.com/projectdiscovery/nuclei/discussions/categories/q-a) +- Join the [Discord server](https://discord.gg/projectdiscovery) #nuclei channel +- Check existing discussions for similar questions + +## Discussion to Issue Conversion Process + +Only maintainers can convert discussions to issues. The process: + +1. **Validation** - Maintainers review the discussion for completeness and validity +2. **Classification** - Determine if it's a bug, feature, enhancement, etc. +3. **Issue creation** - Create a properly formatted issue with appropriate labels +4. **Linking** - Link the issue back to the original discussion +5. **Resolution** - Mark the discussion as resolved or close it + +This process ensures: +- High-quality issues that are actionable +- Proper triage and labeling +- Reduced noise in the issue tracker +- Community involvement in the validation process + +## Why This Process? + +- **Better organization** - Issues contain only validated, actionable items +- **Community input** - Discussions allow for community feedback before escalation +- **Quality control** - Maintainers ensure proper formatting and information +- **Reduced maintenance** - Fewer invalid or duplicate issues to manage +- **Clear separation** - Questions vs. actual bugs/features are clearly distinguished diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d849b1032..01b0a8e4e 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,14 +2,22 @@ blank_issues_enabled: false contact_links: - - name: Ask an question / advise on using nuclei + - name: 🐛 Report a Bug (Start with Discussion) url: https://github.com/projectdiscovery/nuclei/discussions/categories/q-a - about: Ask a question or request support for using nuclei + about: Start by reporting your issue in discussions for proper triage. Issues will be created after review to avoid duplicate/invalid reports. - - name: Share idea / feature to discuss for nuclei + - name: 💡 Request a Feature (Start with Discussion) url: https://github.com/projectdiscovery/nuclei/discussions/categories/ideas - about: Share idea / feature to discuss for nuclei + about: Share your feature idea in discussions first. This helps validate and refine the request before creating an issue. - - name: Connect with PD Team (Discord) + - name: ❓ Ask Questions / Get Help + url: https://github.com/projectdiscovery/nuclei/discussions/categories/q-a + about: Get help and ask questions about using Nuclei. Many questions don't require issues. + + - name: 🔍 Browse Existing Issues + url: https://github.com/projectdiscovery/nuclei/issues + about: Check existing issues to see if your problem has already been reported or is being worked on. + + - name: 💬 Connect with PD Team (Discord) url: https://discord.gg/projectdiscovery - about: Connect with PD Team for direct communication \ No newline at end of file + about: Join our Discord for real-time discussions and community support on the #nuclei channel. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/reference-templates/README.md b/.github/ISSUE_TEMPLATE/reference-templates/README.md new file mode 100644 index 000000000..c170ea1c7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/reference-templates/README.md @@ -0,0 +1,45 @@ +# Issue Template References + +## Overview + +This folder contains the preserved issue templates that are **not** directly accessible to users. These templates serve as references for maintainers when converting discussions to issues. + +## New Workflow + +### For Users: +1. **All reports start in Discussions** - Users cannot create issues directly +2. Bug reports go to [Q&A Discussions](https://github.com/projectdiscovery/nuclei/discussions/categories/q-a) +3. Feature requests go to [Ideas Discussions](https://github.com/projectdiscovery/nuclei/discussions/categories/ideas) +4. This helps filter out duplicate questions, invalid reports, and ensures proper triage + +### For Maintainers: +1. **Review discussions** in both Q&A and Ideas categories +2. **Validate the reports** - ensure they're actual bugs/valid feature requests +3. **Use reference templates** when converting discussions to issues: + - Copy content from `bug-report-reference.yml` or `feature-request-reference.yml` + - Create a new issue manually with the appropriate template structure + - Link back to the original discussion + - Close the discussion or mark it as resolved + +## Benefits + +- **Better triage**: Avoid cluttering issues with questions and invalid reports +- **Community involvement**: Discussions allow for community input before creating issues +- **Quality control**: Maintainers can ensure issues follow proper format and contain necessary information +- **Reduced noise**: Only validated, actionable items become issues + +## Reference Templates + +- `bug-report-reference.yml` - Use when converting bug reports from discussions to issues +- `feature-request-reference.yml` - Use when converting feature requests from discussions to issues + +## Converting a Discussion to Issue + +1. Identify a valid discussion that needs to become an issue +2. Go to the main repository's Issues tab +3. Click "New Issue" +4. Manually create the issue using the reference template structure +5. Include all relevant information from the discussion +6. Add a comment linking back to the original discussion +7. Apply appropriate labels +8. Close or mark the discussion as resolved with a link to the created issue diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/reference-templates/bug-report-reference.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/bug-report.yml rename to .github/ISSUE_TEMPLATE/reference-templates/bug-report-reference.yml diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/reference-templates/feature-request-reference.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/feature-request.yml rename to .github/ISSUE_TEMPLATE/reference-templates/feature-request-reference.yml From 36b4f68eecf1beddcbd22c0086af994a0d2637d8 Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Sun, 31 Aug 2025 03:13:14 +0530 Subject: [PATCH 105/135] misc hyperlink update --- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 01b0a8e4e..1a679d690 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,11 +3,11 @@ blank_issues_enabled: false contact_links: - name: 🐛 Report a Bug (Start with Discussion) - url: https://github.com/projectdiscovery/nuclei/discussions/categories/q-a + url: https://github.com/projectdiscovery/nuclei/discussions/new?category=q-a about: Start by reporting your issue in discussions for proper triage. Issues will be created after review to avoid duplicate/invalid reports. - name: 💡 Request a Feature (Start with Discussion) - url: https://github.com/projectdiscovery/nuclei/discussions/categories/ideas + url: https://github.com/projectdiscovery/nuclei/discussions/new?category=ideas about: Share your feature idea in discussions first. This helps validate and refine the request before creating an issue. - name: ❓ Ask Questions / Get Help From 48c389b063aafb70c25ff639eb6e2ee34e826cf0 Mon Sep 17 00:00:00 2001 From: PDTeamX <8293321+ehsandeep@users.noreply.github.com> Date: Sun, 31 Aug 2025 03:16:13 +0530 Subject: [PATCH 106/135] link update --- .github/ISSUE_TEMPLATE/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 1a679d690..4a0c58e23 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,15 +3,15 @@ blank_issues_enabled: false contact_links: - name: 🐛 Report a Bug (Start with Discussion) - url: https://github.com/projectdiscovery/nuclei/discussions/new?category=q-a + url: https://github.com/orgs/projectdiscovery/discussions/new?category=q-a about: Start by reporting your issue in discussions for proper triage. Issues will be created after review to avoid duplicate/invalid reports. - name: 💡 Request a Feature (Start with Discussion) - url: https://github.com/projectdiscovery/nuclei/discussions/new?category=ideas + url: https://github.com/orgs/projectdiscovery/discussions/new?category=ideas about: Share your feature idea in discussions first. This helps validate and refine the request before creating an issue. - name: ❓ Ask Questions / Get Help - url: https://github.com/projectdiscovery/nuclei/discussions/categories/q-a + url: https://github.com/orgs/projectdiscovery/discussions about: Get help and ask questions about using Nuclei. Many questions don't require issues. - name: 🔍 Browse Existing Issues From 32dfeacd9d630e1dba2567134193e64054687660 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 17:52:46 +0700 Subject: [PATCH 107/135] chore(deps): bump the modules group across 1 directory with 11 updates (#6438) * chore(deps): bump the modules group across 1 directory with 11 updates Bumps the modules group with 10 updates in the / directory: | Package | From | To | | --- | --- | --- | | [github.com/projectdiscovery/fastdialer](https://github.com/projectdiscovery/fastdialer) | `0.4.6` | `0.4.7` | | [github.com/projectdiscovery/hmap](https://github.com/projectdiscovery/hmap) | `0.0.92` | `0.0.93` | | [github.com/projectdiscovery/retryabledns](https://github.com/projectdiscovery/retryabledns) | `1.0.105` | `1.0.106` | | [github.com/projectdiscovery/retryablehttp-go](https://github.com/projectdiscovery/retryablehttp-go) | `1.0.120` | `1.0.121` | | [github.com/projectdiscovery/dsl](https://github.com/projectdiscovery/dsl) | `0.5.0` | `0.5.1` | | [github.com/projectdiscovery/gozero](https://github.com/projectdiscovery/gozero) | `0.0.3` | `0.1.0` | | [github.com/projectdiscovery/ratelimit](https://github.com/projectdiscovery/ratelimit) | `0.0.81` | `0.0.82` | | [github.com/projectdiscovery/tlsx](https://github.com/projectdiscovery/tlsx) | `1.1.9` | `1.2.0` | | [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) | `0.2.37` | `0.2.43` | | [github.com/projectdiscovery/cdncheck](https://github.com/projectdiscovery/cdncheck) | `1.1.27` | `1.1.33` | Updates `github.com/projectdiscovery/fastdialer` from 0.4.6 to 0.4.7 - [Release notes](https://github.com/projectdiscovery/fastdialer/releases) - [Commits](https://github.com/projectdiscovery/fastdialer/compare/v0.4.6...v0.4.7) Updates `github.com/projectdiscovery/hmap` from 0.0.92 to 0.0.93 - [Release notes](https://github.com/projectdiscovery/hmap/releases) - [Commits](https://github.com/projectdiscovery/hmap/compare/v0.0.92...v0.0.93) Updates `github.com/projectdiscovery/retryabledns` from 1.0.105 to 1.0.106 - [Release notes](https://github.com/projectdiscovery/retryabledns/releases) - [Commits](https://github.com/projectdiscovery/retryabledns/compare/v1.0.105...v1.0.106) Updates `github.com/projectdiscovery/retryablehttp-go` from 1.0.120 to 1.0.121 - [Release notes](https://github.com/projectdiscovery/retryablehttp-go/releases) - [Commits](https://github.com/projectdiscovery/retryablehttp-go/compare/v1.0.120...v1.0.121) Updates `github.com/projectdiscovery/dsl` from 0.5.0 to 0.5.1 - [Release notes](https://github.com/projectdiscovery/dsl/releases) - [Commits](https://github.com/projectdiscovery/dsl/compare/v0.5.0...v0.5.1) Updates `github.com/projectdiscovery/gozero` from 0.0.3 to 0.1.0 - [Release notes](https://github.com/projectdiscovery/gozero/releases) - [Commits](https://github.com/projectdiscovery/gozero/compare/v0.0.3...v0.1.0) Updates `github.com/projectdiscovery/networkpolicy` from 0.1.20 to 0.1.21 - [Release notes](https://github.com/projectdiscovery/networkpolicy/releases) - [Commits](https://github.com/projectdiscovery/networkpolicy/compare/v0.1.20...v0.1.21) Updates `github.com/projectdiscovery/ratelimit` from 0.0.81 to 0.0.82 - [Release notes](https://github.com/projectdiscovery/ratelimit/releases) - [Commits](https://github.com/projectdiscovery/ratelimit/compare/v0.0.81...v0.0.82) Updates `github.com/projectdiscovery/tlsx` from 1.1.9 to 1.2.0 - [Release notes](https://github.com/projectdiscovery/tlsx/releases) - [Changelog](https://github.com/projectdiscovery/tlsx/blob/main/.goreleaser.yml) - [Commits](https://github.com/projectdiscovery/tlsx/compare/v1.1.9...v1.2.0) Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.37 to 0.2.43 - [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases) - [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.37...v0.2.43) Updates `github.com/projectdiscovery/cdncheck` from 1.1.27 to 1.1.33 - [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.27...v1.1.33) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/fastdialer dependency-version: 0.4.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/hmap dependency-version: 0.0.93 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/retryabledns dependency-version: 1.0.106 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/retryablehttp-go dependency-version: 1.0.121 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/dsl dependency-version: 0.5.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/gozero dependency-version: 0.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: modules - dependency-name: github.com/projectdiscovery/networkpolicy dependency-version: 0.1.21 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/ratelimit dependency-version: 0.0.82 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/tlsx dependency-version: 1.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: modules - dependency-name: github.com/projectdiscovery/wappalyzergo dependency-version: 0.2.43 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/cdncheck dependency-version: 1.1.33 dependency-type: indirect update-type: version-update:semver-patch dependency-group: modules ... Signed-off-by: dependabot[bot] * bump * httpx dev * mod tidy --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mzack9999 --- go.mod | 40 ++++++++++++------------ go.sum | 96 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/go.mod b/go.mod index 028bf8f6a..a862ed233 100644 --- a/go.mod +++ b/go.mod @@ -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.6 - github.com/projectdiscovery/hmap v0.0.92 + github.com/projectdiscovery/fastdialer v0.4.7 + github.com/projectdiscovery/hmap v0.0.93 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.120 + github.com/projectdiscovery/retryabledns v1.0.106 + github.com/projectdiscovery/retryablehttp-go v1.0.121 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.0 @@ -35,9 +35,9 @@ 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.50.0 go.uber.org/multierr v1.11.0 - golang.org/x/net v0.42.0 + golang.org/x/net v0.43.0 golang.org/x/oauth2 v0.30.0 golang.org/x/text v0.28.0 gopkg.in/yaml.v2 v2.4.0 @@ -87,26 +87,26 @@ require ( github.com/microsoft/go-mssqldb v1.9.2 github.com/ory/dockertest/v3 v3.12.0 github.com/praetorian-inc/fingerprintx v1.1.15 - github.com/projectdiscovery/dsl v0.5.0 + github.com/projectdiscovery/dsl v0.5.1 github.com/projectdiscovery/fasttemplate v0.0.2 github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb github.com/projectdiscovery/goflags v0.1.74 github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/gostruct v0.0.2 - github.com/projectdiscovery/gozero v0.0.3 - github.com/projectdiscovery/httpx v1.7.1 + github.com/projectdiscovery/gozero v0.1.0 + github.com/projectdiscovery/httpx v1.7.1-0.20250901093029-3909667cbaa6 github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 - github.com/projectdiscovery/networkpolicy v0.1.20 - github.com/projectdiscovery/ratelimit v0.0.81 + github.com/projectdiscovery/networkpolicy v0.1.21 + github.com/projectdiscovery/ratelimit v0.0.82 github.com/projectdiscovery/rdap v0.9.0 github.com/projectdiscovery/sarif v0.0.1 - github.com/projectdiscovery/tlsx v1.1.9 + github.com/projectdiscovery/tlsx v1.2.1 github.com/projectdiscovery/uncover v1.1.0 github.com/projectdiscovery/useragent v0.0.101 github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4 - github.com/projectdiscovery/wappalyzergo v0.2.37 + github.com/projectdiscovery/wappalyzergo v0.2.43 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -181,7 +181,7 @@ require ( github.com/charmbracelet/x/cellbuf v0.0.13 // indirect github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/cheggaaa/pb/v3 v3.1.4 // indirect + github.com/cheggaaa/pb/v3 v3.1.6 // indirect github.com/cloudflare/cfssl v1.6.4 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect @@ -209,7 +209,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // 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.23.1 // indirect + github.com/gaissmai/bart v0.24.0 // 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 @@ -232,7 +232,7 @@ require ( github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/certificate-transparency-go v1.1.4 // indirect + github.com/google/certificate-transparency-go v1.3.2 // indirect github.com/google/go-github/v30 v30.1.0 // indirect github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect @@ -312,7 +312,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.27 // indirect + github.com/projectdiscovery/cdncheck v1.1.33 // indirect 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 @@ -384,8 +384,8 @@ require ( github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // indirect - go.etcd.io/bbolt v1.3.10 // indirect - go.uber.org/zap v1.25.0 // indirect + go.etcd.io/bbolt v1.4.0 // indirect + go.uber.org/zap v1.27.0 // indirect goftp.io/server/v2 v2.0.1 // indirect golang.org/x/crypto v0.41.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b @@ -393,7 +393,7 @@ require ( golang.org/x/sys v0.35.0 // indirect golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.35.0 - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index 8e24f0a5d..ea91f7cec 100644 --- a/go.sum +++ b/go.sum @@ -447,8 +447,6 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -509,8 +507,8 @@ github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Y github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo= -github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA= +github.com/cheggaaa/pb/v3 v3.1.6 h1:h0x+vd7EiUohAJ29DJtJy+SNAc55t/elW3jCD086EXk= +github.com/cheggaaa/pb/v3 v3.1.6/go.mod h1:urxmfVtaxT+9aWk92DbsvXFZtNSWQSO5TRAp+MJ3l1s= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -656,8 +654,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.23.1 h1:8+EYZZcm9xObBgCIBb8f5sg65qVtphg7VcbMOjuvNrE= -github.com/gaissmai/bart v0.23.1/go.mod h1:RpLtt3lWq1BoRz3AAyDAJ7jhLWBkYhVCfi+ximB2t68= +github.com/gaissmai/bart v0.24.0 h1:HOq5aXDBa4d376KkuxD+xnS9DQWWJtD4zgDNoGV0KrQ= +github.com/gaissmai/bart v0.24.0/go.mod h1:RpLtt3lWq1BoRz3AAyDAJ7jhLWBkYhVCfi+ximB2t68= 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= @@ -820,8 +818,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= -github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= +github.com/google/certificate-transparency-go v1.3.2 h1:9ahSNZF2o7SYMaKaXhAumVEzXB2QaayzII9C8rv7v+A= +github.com/google/certificate-transparency-go v1.3.2/go.mod h1:H5FpMUaGa5Ab2+KCYsxg6sELw3Flkl7pGZzWdBoYLXs= github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -934,8 +932,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hamba/avro/v2 v2.17.2/go.mod h1:Q9YK+qxAhtVrNqOhwlZTATLgLA8qxG2vtvkhK8fJ7Jo= @@ -1238,14 +1237,14 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.27 h1:ZuSyIG0kxI5voWIZzIYVDm3DIe+vN63oPb8d5GIdRLA= -github.com/projectdiscovery/cdncheck v1.1.27/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.33 h1:xQYq+ms0yaLaiK1BbfNc9pKsrnYVLhwRMF4yJWNfMn4= +github.com/projectdiscovery/cdncheck v1.1.33/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= 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.6 h1:7cw47IyrkVHCEM80dBDhjT4YNsPY2IAZD2Sg11QM0Wk= -github.com/projectdiscovery/fastdialer v0.4.6/go.mod h1:IRbTB9d2GNT1EyxA16b/HJpqYbnNXk6hsH8CRZkdukc= +github.com/projectdiscovery/dsl v0.5.1 h1:Nm6ToWtNKrhrF880qWykbub60Lw4m96ZkB43OGOsVLg= +github.com/projectdiscovery/dsl v0.5.1/go.mod h1:m+tLImvmlEnFTuwb0Bm3DqCL6e7sWOunJyxFi27AduI= +github.com/projectdiscovery/fastdialer v0.4.7 h1:fErLAppGZtZMGLLyeInMh4Kw/N0FXlTVh35v07dpS7I= +github.com/projectdiscovery/fastdialer v0.4.7/go.mod h1:0Nm8GgU3Ds2Ac3/Fg59mVG40eMFYNA426PAcYqeNioM= 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= @@ -1260,12 +1259,12 @@ github.com/projectdiscovery/gologger v1.1.54 h1:WMzvJ8j/4gGfPKpCttSTaYCVDU1MWQSJ github.com/projectdiscovery/gologger v1.1.54/go.mod h1:vza/8pe2OKOt+ujFWncngknad1XWr8EnLKlbcejOyUE= github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M= 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/httpx v1.7.1 h1:XmhUGGUdmpWWXyQC8utV9gyHVrjzXBcT2SAUOgFOQV8= -github.com/projectdiscovery/httpx v1.7.1/go.mod h1:fejxELITLvQ0uXB/pnBiekjMmGdoE7+7p+DpIYhAhJU= +github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mnag8zXIAQI= +github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs= +github.com/projectdiscovery/hmap v0.0.93 h1:iIRdioT4byGJ4Hz5cOjo1fd3HFFi1MUFPv+EGYc1yng= +github.com/projectdiscovery/hmap v0.0.93/go.mod h1:oKgtWo2QMD7BkW25ezYbFCqKO3IctZ2ByEaG2XWW0t0= +github.com/projectdiscovery/httpx v1.7.1-0.20250901093029-3909667cbaa6 h1:LrO3ryyJikuyZmHk/vWlQGnio65gVIqkgQK1+2L80+Q= +github.com/projectdiscovery/httpx v1.7.1-0.20250901093029-3909667cbaa6/go.mod h1:lV4GZJb6TArwq/VT+AdZbysG+Ukneyfr9cXsYTrLbbE= github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI= github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc= github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8= @@ -1276,32 +1275,32 @@ 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.20 h1:dPUk3FKoAehMnFvphAZLq6khDCbPYPJnD6PPTcjp5nU= -github.com/projectdiscovery/networkpolicy v0.1.20/go.mod h1:laPi8mLbgCbYZ0kYQU4fkWCFQdFbx24ci7yBQA8Hcww= -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/networkpolicy v0.1.21 h1:BOlYxPyrfqb5DneyuokZkRpeX5MCXLjCH4sI2hLudII= +github.com/projectdiscovery/networkpolicy v0.1.21/go.mod h1:/DI9DZANBQ20x09mvcHA0J/3dCLBgCkEW5r5/L1b87U= +github.com/projectdiscovery/ratelimit v0.0.82 h1:rtO5SQf5uQFu5zTahTaTcO06OxmG8EIF1qhdFPIyTak= +github.com/projectdiscovery/ratelimit v0.0.82/go.mod h1:z076BrLkBb5yS7uhHNoCTf8X/BvFSGRxwQ8EzEL9afM= 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.120 h1:kH4D0MwKV6a0U6YbBQ8cBD+tT0U3zrwudTPCFVSaZg8= -github.com/projectdiscovery/retryablehttp-go v1.0.120/go.mod h1:jR3eJLdCEvW3Xz0LOQldxNc+MHHY61qZh9k3Sz7U40U= +github.com/projectdiscovery/retryabledns v1.0.106 h1:repm5aGq5ge6fNJQbPNux7vyUhtUju7aIMEXZD9FX0A= +github.com/projectdiscovery/retryabledns v1.0.106/go.mod h1:1W3ogENvt3Pb+Ju4AN0aE2lZy+D76Yzxsz51DqFCIk8= +github.com/projectdiscovery/retryablehttp-go v1.0.121 h1:KQcMS7z5k3xnrTnD5G+HOVp1YRIbaB/iA+moc2lkR4c= +github.com/projectdiscovery/retryablehttp-go v1.0.121/go.mod h1:15Usp6eLzNM/mI/jd+ucYRiyUuvm7vg2ymWRylG/Zss= 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= github.com/projectdiscovery/stringsutil v0.0.2/go.mod h1:EJ3w6bC5fBYjVou6ryzodQq37D5c6qbAYQpGmAy+DC0= -github.com/projectdiscovery/tlsx v1.1.9 h1:DhErhHCO2+toF5DEX7qe3pkwrIrYlex3F/mzHEUiZHg= -github.com/projectdiscovery/tlsx v1.1.9/go.mod h1:Jy+r38WyYjapQWaffiKGdYm4Ksdrt8BWtsqA2rUospU= +github.com/projectdiscovery/tlsx v1.2.1 h1:R8QgKb/vxd6Y0cfGFBYs4nn0zodHABeeLPqJjs2mNrA= +github.com/projectdiscovery/tlsx v1.2.1/go.mod h1:p19UHGQ6bvcbvhO4NvYBKOxlE4QvrUaectx9g/Mm3JA= github.com/projectdiscovery/uncover v1.1.0 h1:UDp/qLZn78YZb6VPoOrfyP1vz+ojEx8VrTTyjjRt9UU= 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.24-0.20250823123502-bd7f2849ddb4 h1:qQMEhfxDsiZ+Ay3dj93FuMAa7yt1XE2bxDpPSTEz/P0= github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4/go.mod h1:ipzU2PHYP71MaMn4jllPOpdYpdMkFD0jE3Tjak4b4eM= -github.com/projectdiscovery/wappalyzergo v0.2.37 h1:O4XgDKCWAXQT1mEJrLHX88vk+fCEUzNPdpJPAvvAhg0= -github.com/projectdiscovery/wappalyzergo v0.2.37/go.mod h1:L4P6SZuaEgEE2eXbpf4OnSGxjWj9vn6xM15SD78niLA= +github.com/projectdiscovery/wappalyzergo v0.2.43 h1:gmjBJv2xHFBl48B0yFe2OL6v+mXe4KMLNdEmuMpqfhk= +github.com/projectdiscovery/wappalyzergo v0.2.43/go.mod h1:N2ZzJYLz1FEyLO4oIL0scz8Z/r2eRRylKFrt3Zy25tc= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1480,8 +1479,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.50.0 h1:M178k6l8cnh9T1c1cStkhytVxdk5zPd6gGZf8ySIuVo= +github.com/weppos/publicsuffix-go v0.50.0/go.mod h1:VXhClBYMlDrUsome4pOTpe68Ui0p6iQRAbyHQD1yKoU= 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= @@ -1569,8 +1568,8 @@ github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnT gitlab.com/gitlab-org/api/client-go v0.130.1 h1:1xF5C5Zq3sFeNg3PzS2z63oqrxifne3n/OnbI7nptRc= gitlab.com/gitlab-org/api/client-go v0.130.1/go.mod h1:ZhSxLAWadqP6J9lMh40IAZOlOxBLPRh7yFOXR/bMJWM= go.einride.tech/aip v0.67.1/go.mod h1:ZGX4/zKw8dcgzdLsrvpOOGxfxI2QSk12SlP7d6c0/XI= -go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= -go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= +go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -1599,8 +1598,8 @@ go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFu go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= @@ -1626,14 +1625,15 @@ go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXe go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= goftp.io/server/v2 v2.0.1 h1:H+9UbCX2N206ePDSVNCjBftOKOgil6kQ5RAQNx5hJwE= @@ -1834,8 +1834,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2347,8 +2347,8 @@ google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDom google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2371,8 +2371,8 @@ google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 9c64a1cb9b199356598f2dc9af4ed3fa9cd4bb52 Mon Sep 17 00:00:00 2001 From: mkrs2404 Date: Fri, 5 Sep 2025 19:53:26 +0530 Subject: [PATCH 108/135] Reporting validation (#6456) * add custom validator for reporting issues * use httpx dev branch * remove yaml marshal/unmarshal for validator callback --- go.mod | 4 ++-- go.sum | 8 ++++---- pkg/reporting/options.go | 3 +++ pkg/reporting/reporting.go | 4 ++++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a862ed233..f8ac019fa 100644 --- a/go.mod +++ b/go.mod @@ -95,7 +95,7 @@ require ( github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/gostruct v0.0.2 github.com/projectdiscovery/gozero v0.1.0 - github.com/projectdiscovery/httpx v1.7.1-0.20250901093029-3909667cbaa6 + github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 github.com/projectdiscovery/networkpolicy v0.1.21 @@ -352,7 +352,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/ysmood/fetchup v0.2.3 // indirect github.com/ysmood/got v0.40.0 // indirect - github.com/yuin/goldmark v1.7.8 // indirect + github.com/yuin/goldmark v1.7.11 // indirect github.com/yuin/goldmark-emoji v1.0.5 // indirect github.com/zcalusic/sysinfo v1.0.2 // indirect github.com/zeebo/blake3 v0.2.3 // indirect diff --git a/go.sum b/go.sum index ea91f7cec..ae2cdea3d 100644 --- a/go.sum +++ b/go.sum @@ -1263,8 +1263,8 @@ github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mna github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs= github.com/projectdiscovery/hmap v0.0.93 h1:iIRdioT4byGJ4Hz5cOjo1fd3HFFi1MUFPv+EGYc1yng= github.com/projectdiscovery/hmap v0.0.93/go.mod h1:oKgtWo2QMD7BkW25ezYbFCqKO3IctZ2ByEaG2XWW0t0= -github.com/projectdiscovery/httpx v1.7.1-0.20250901093029-3909667cbaa6 h1:LrO3ryyJikuyZmHk/vWlQGnio65gVIqkgQK1+2L80+Q= -github.com/projectdiscovery/httpx v1.7.1-0.20250901093029-3909667cbaa6/go.mod h1:lV4GZJb6TArwq/VT+AdZbysG+Ukneyfr9cXsYTrLbbE= +github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f h1:Z73qF1ilD5RUsZP4Px4JImFkCTRlQ5K8uR2gm9eakw8= +github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f/go.mod h1:hGAOnHyiq80ASpwbycv8Q32wsfcI8xtADEDw/mKPqTs= github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI= github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc= github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8= @@ -1535,8 +1535,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= -github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo= +github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk= github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= diff --git a/pkg/reporting/options.go b/pkg/reporting/options.go index bbee7b207..eb1fbaaa2 100644 --- a/pkg/reporting/options.go +++ b/pkg/reporting/options.go @@ -1,6 +1,7 @@ package reporting import ( + "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/es" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonexporter" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonl" @@ -23,6 +24,8 @@ type Options struct { AllowList *filters.Filter `yaml:"allow-list"` // DenyList contains a list of denied events for reporting module DenyList *filters.Filter `yaml:"deny-list"` + // ValidatorCallback is a callback function that is called to validate an event before it is reported + ValidatorCallback func(event *output.ResultEvent) bool `yaml:"-"` // GitHub contains configuration options for GitHub Issue Tracker GitHub *github.Options `yaml:"github"` // GitLab contains configuration options for GitLab Issue Tracker diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index a048e9478..c3706c970 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -288,6 +288,10 @@ func (c *ReportingClient) CreateIssue(event *output.ResultEvent) error { return nil } + if c.options.ValidatorCallback != nil && !c.options.ValidatorCallback(event) { + return nil + } + var err error unique := true if c.dedupe != nil { From ff5734ba1544f8cd22c2c3e9d5f87e848f0e202e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 17:34:42 +0700 Subject: [PATCH 109/135] chore(deps): bump the workflows group across 1 directory with 2 updates (#6462) Bumps the workflows group with 2 updates in the / directory: [actions/checkout](https://github.com/actions/checkout) and [actions/stale](https://github.com/actions/stale). Updates `actions/checkout` from 4 to 5 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) Updates `actions/stale` from 9 to 10 - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v9...v10) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major dependency-group: workflows - dependency-name: actions/stale dependency-version: '10' dependency-type: direct:production update-type: version-update:semver-major dependency-group: workflows ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/auto-merge.yaml | 2 +- .github/workflows/compat-checks.yaml | 2 +- .github/workflows/generate-docs.yaml | 2 +- .github/workflows/generate-pgo.yaml | 2 +- .github/workflows/govulncheck.yaml | 2 +- .github/workflows/perf-regression.yaml | 2 +- .github/workflows/perf-test.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/stale.yaml | 2 +- .github/workflows/tests.yaml | 18 +++++++++--------- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/auto-merge.yaml b/.github/workflows/auto-merge.yaml index 0ff3098e6..ad2890dda 100644 --- a/.github/workflows/auto-merge.yaml +++ b/.github/workflows/auto-merge.yaml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: token: ${{ secrets.DEPENDABOT_PAT }} diff --git a/.github/workflows/compat-checks.yaml b/.github/workflows/compat-checks.yaml index 589b9a2f1..8a9080b90 100644 --- a/.github/workflows/compat-checks.yaml +++ b/.github/workflows/compat-checks.yaml @@ -13,7 +13,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go/compat-checks@v1 with: release-test: true diff --git a/.github/workflows/generate-docs.yaml b/.github/workflows/generate-docs.yaml index 939b9bc69..a68ff7d97 100644 --- a/.github/workflows/generate-docs.yaml +++ b/.github/workflows/generate-docs.yaml @@ -11,7 +11,7 @@ jobs: if: "${{ !endsWith(github.actor, '[bot]') }}" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - uses: projectdiscovery/actions/setup/git@v1 - run: make syntax-docs diff --git a/.github/workflows/generate-pgo.yaml b/.github/workflows/generate-pgo.yaml index 463e7d686..c10743b98 100644 --- a/.github/workflows/generate-pgo.yaml +++ b/.github/workflows/generate-pgo.yaml @@ -28,7 +28,7 @@ jobs: LIST_FILE: "/tmp/targets-${{ matrix.targets }}.txt" PROFILE_MEM: "/tmp/nuclei-profile-${{ matrix.targets }}-targets" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/git@v1 - uses: projectdiscovery/actions/setup/go@v1 - name: Generate list diff --git a/.github/workflows/govulncheck.yaml b/.github/workflows/govulncheck.yaml index 1a116fa8f..9796b709e 100644 --- a/.github/workflows/govulncheck.yaml +++ b/.github/workflows/govulncheck.yaml @@ -16,7 +16,7 @@ jobs: env: OUTPUT: "/tmp/results.sarif" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - run: go install golang.org/x/vuln/cmd/govulncheck@latest - run: govulncheck -scan package -format sarif ./... > $OUTPUT diff --git a/.github/workflows/perf-regression.yaml b/.github/workflows/perf-regression.yaml index 090f722eb..8e7e7eed5 100644 --- a/.github/workflows/perf-regression.yaml +++ b/.github/workflows/perf-regression.yaml @@ -11,7 +11,7 @@ jobs: env: BENCH_OUT: "/tmp/bench.out" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - run: make build-test - run: ./bin/nuclei.test -test.run - -test.bench=. -test.benchmem ./cmd/nuclei/ | tee $BENCH_OUT diff --git a/.github/workflows/perf-test.yaml b/.github/workflows/perf-test.yaml index 94dec5cbd..4ee8408c9 100644 --- a/.github/workflows/perf-test.yaml +++ b/.github/workflows/perf-test.yaml @@ -16,7 +16,7 @@ jobs: LIST_FILE: "/tmp/targets-${{ matrix.count }}.txt" PROFILE_MEM: "/tmp/nuclei-perf-test-${{ matrix.count }}" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - run: make verify - name: Generate list diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3eb36e7e2..4d9d412dd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,7 +10,7 @@ jobs: release: runs-on: ubuntu-latest-16-cores steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 - uses: projectdiscovery/actions/setup/go@v1 diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 2b336b671..efa88506d 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -13,7 +13,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: days-before-stale: 90 days-before-close: 7 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index f8297c107..cc7f7b989 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -22,7 +22,7 @@ jobs: if: "${{ !endsWith(github.actor, '[bot]') }}" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - uses: projectdiscovery/actions/golangci-lint/v2@v1 @@ -35,7 +35,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] runs-on: "${{ matrix.os }}" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - run: make vet - run: make build @@ -52,7 +52,7 @@ jobs: needs: ["tests"] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - name: "Simple" run: go run . @@ -74,7 +74,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - uses: projectdiscovery/actions/setup/python@v1 - run: bash run.sh "${{ matrix.os }}" @@ -93,7 +93,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - uses: projectdiscovery/actions/setup/python@v1 - run: bash run.sh @@ -106,7 +106,7 @@ jobs: needs: ["tests"] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - run: make template-validate @@ -119,7 +119,7 @@ jobs: contents: read security-events: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: github/codeql-action/init@v3 with: languages: 'go' @@ -131,7 +131,7 @@ jobs: needs: ["tests"] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: projectdiscovery/actions/setup/go@v1 - uses: projectdiscovery/actions/goreleaser@v1 @@ -143,7 +143,7 @@ jobs: TARGET_URL: "http://scanme.sh/a/?b=c" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: make build - name: "Setup environment (push)" if: ${{ github.event_name == 'push' }} From 218a2f69a5bf51972f6041cbb231fdb6dbc350ee Mon Sep 17 00:00:00 2001 From: Ice3man Date: Wed, 10 Sep 2025 16:51:20 +0530 Subject: [PATCH 110/135] feat: added new text/template syntax to jira custom fields --- pkg/reporting/trackers/jira/jira.go | 140 +++++++++++++++++++---- pkg/reporting/trackers/jira/jira_test.go | 61 ++++++++++ 2 files changed, 176 insertions(+), 25 deletions(-) diff --git a/pkg/reporting/trackers/jira/jira.go b/pkg/reporting/trackers/jira/jira.go index bfb518daa..5e8d45bff 100644 --- a/pkg/reporting/trackers/jira/jira.go +++ b/pkg/reporting/trackers/jira/jira.go @@ -1,12 +1,14 @@ package jira import ( + "bytes" "fmt" "io" "net/http" "net/url" "strings" "sync" + "text/template" "github.com/andygrunwald/go-jira" "github.com/pkg/errors" @@ -25,6 +27,105 @@ type Formatter struct { util.MarkdownFormatter } +// TemplateContext holds the data available for template evaluation +type TemplateContext struct { + Severity string + Name string + Host string + CVSSScore string + CVEID string + CWEID string + CVSSMetrics string + Tags []string +} + +// buildTemplateContext creates a template context from a ResultEvent +func buildTemplateContext(event *output.ResultEvent) *TemplateContext { + ctx := &TemplateContext{ + Host: event.Host, + Name: event.Info.Name, + Tags: event.Info.Tags.ToSlice(), + } + + // Set severity string + ctx.Severity = event.Info.SeverityHolder.Severity.String() + + if event.Info.Classification != nil { + ctx.CVSSScore = fmt.Sprintf("%.2f", ptr.Safe(event.Info.Classification).CVSSScore) + ctx.CVEID = strings.Join(ptr.Safe(event.Info.Classification).CVEID.ToSlice(), ", ") + ctx.CWEID = strings.Join(ptr.Safe(event.Info.Classification).CWEID.ToSlice(), ", ") + ctx.CVSSMetrics = ptr.Safe(event.Info.Classification).CVSSMetrics + } + + return ctx +} + +// evaluateTemplate executes a template string with the given context +func evaluateTemplate(templateStr string, ctx *TemplateContext) (string, error) { + // If no template markers found, return as-is for backward compatibility + if !strings.Contains(templateStr, "{{") { + return templateStr, nil + } + + tmpl, err := template.New("field").Parse(templateStr) + if err != nil { + return templateStr, fmt.Errorf("failed to parse template: %w", err) + } + + var buf bytes.Buffer + if err := tmpl.Execute(&buf, ctx); err != nil { + return templateStr, fmt.Errorf("failed to execute template: %w", err) + } + + return buf.String(), nil +} + +// evaluateCustomFieldValue evaluates a custom field value, supporting both new template syntax and legacy $variable syntax +func (i *Integration) evaluateCustomFieldValue(value string, templateCtx *TemplateContext, event *output.ResultEvent) (interface{}, error) { + // Try template evaluation first (supports {{...}} syntax) + if strings.Contains(value, "{{") { + return evaluateTemplate(value, templateCtx) + } + + // Handle legacy $variable syntax for backward compatibility + if strings.HasPrefix(value, "$") { + variableName := strings.TrimPrefix(value, "$") + switch variableName { + case "CVSSMetrics": + if event.Info.Classification != nil { + return ptr.Safe(event.Info.Classification).CVSSMetrics, nil + } + return "", nil + case "CVEID": + if event.Info.Classification != nil { + return strings.Join(ptr.Safe(event.Info.Classification).CVEID.ToSlice(), ", "), nil + } + return "", nil + case "CWEID": + if event.Info.Classification != nil { + return strings.Join(ptr.Safe(event.Info.Classification).CWEID.ToSlice(), ", "), nil + } + return "", nil + case "CVSSScore": + if event.Info.Classification != nil { + return fmt.Sprintf("%.2f", ptr.Safe(event.Info.Classification).CVSSScore), nil + } + return "", nil + case "Host": + return event.Host, nil + case "Severity": + return event.Info.SeverityHolder.Severity.String(), nil + case "Name": + return event.Info.Name, nil + default: + return value, nil // return as-is if variable not found + } + } + + // Return as-is if no template or variable syntax found + return value, nil +} + func (jiraFormatter *Formatter) MakeBold(text string) string { return "*" + text + "*" } @@ -155,12 +256,12 @@ func (i *Integration) CreateNewIssue(event *output.ResultEvent) (*filters.Create if label := i.options.IssueType; label != "" { labels = append(labels, label) } - // for each custom value, take the name of the custom field and - // set the value of the custom field to the value specified in the - // configuration options + // Build template context for evaluating custom field templates + templateCtx := buildTemplateContext(event) + + // Process custom fields with template evaluation support customFields := tcontainer.NewMarshalMap() for name, value := range i.options.CustomFields { - //customFields[name] = map[string]interface{}{"value": value} if valueMap, ok := value.(map[interface{}]interface{}); ok { // Iterate over nested map for nestedName, nestedValue := range valueMap { @@ -168,32 +269,21 @@ func (i *Integration) CreateNewIssue(event *output.ResultEvent) (*filters.Create if !ok { return nil, fmt.Errorf(`couldn't iterate on nested item "%s": %s`, nestedName, nestedValue) } - if strings.HasPrefix(fmtNestedValue, "$") { - nestedValue = strings.TrimPrefix(fmtNestedValue, "$") - switch nestedValue { - case "CVSSMetrics": - nestedValue = ptr.Safe(event.Info.Classification).CVSSMetrics - case "CVEID": - nestedValue = ptr.Safe(event.Info.Classification).CVEID - case "CWEID": - nestedValue = ptr.Safe(event.Info.Classification).CWEID - case "CVSSScore": - nestedValue = ptr.Safe(event.Info.Classification).CVSSScore - case "Host": - nestedValue = event.Host - case "Severity": - nestedValue = event.Info.SeverityHolder - case "Name": - nestedValue = event.Info.Name - } + + // Evaluate template or handle legacy $variable syntax + evaluatedValue, err := i.evaluateCustomFieldValue(fmtNestedValue, templateCtx, event) + if err != nil { + gologger.Warning().Msgf("Failed to evaluate template for field %s.%s: %v", name, nestedName, err) + evaluatedValue = fmtNestedValue // fallback to original value } + switch nestedName { case "id": - customFields[name] = map[string]interface{}{"id": nestedValue} + customFields[name] = map[string]interface{}{"id": evaluatedValue} case "name": - customFields[name] = map[string]interface{}{"value": nestedValue} + customFields[name] = map[string]interface{}{"value": evaluatedValue} case "freeform": - customFields[name] = nestedValue + customFields[name] = evaluatedValue } } } diff --git a/pkg/reporting/trackers/jira/jira_test.go b/pkg/reporting/trackers/jira/jira_test.go index d725a97b2..49ae365e6 100644 --- a/pkg/reporting/trackers/jira/jira_test.go +++ b/pkg/reporting/trackers/jira/jira_test.go @@ -6,6 +6,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/model" "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" + "github.com/projectdiscovery/nuclei/v3/pkg/model/types/stringslice" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/filters" "github.com/stretchr/testify/require" @@ -70,3 +71,63 @@ func Test_ShouldFilter_Tracker(t *testing.T) { }})) }) } + +func TestTemplateEvaluation(t *testing.T) { + event := &output.ResultEvent{ + Host: "example.com", + Info: model.Info{ + Name: "Test Vulnerability", + SeverityHolder: severity.Holder{Severity: severity.Critical}, + Classification: &model.Classification{ + CVSSScore: 9.8, + CVEID: stringslice.StringSlice{Value: []string{"CVE-2023-1234"}}, + CWEID: stringslice.StringSlice{Value: []string{"CWE-79"}}, + CVSSMetrics: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + }, + }, + } + + integration := &Integration{} + + t.Run("conditional template", func(t *testing.T) { + templateStr := `{{if eq .Severity "critical"}}11187{{else if eq .Severity "high"}}11186{{else if eq .Severity "medium"}}11185{{else}}11184{{end}}` + result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "11187", result) + }) + + t.Run("freeform description template", func(t *testing.T) { + templateStr := `Vulnerability detected by Nuclei. Name: {{.Name}}, Severity: {{.Severity}}, Host: {{.Host}}` + result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event) + require.NoError(t, err) + expected := "Vulnerability detected by Nuclei. Name: Test Vulnerability, Severity: critical, Host: example.com" + require.Equal(t, expected, result) + }) + + t.Run("legacy variable syntax", func(t *testing.T) { + result, err := integration.evaluateCustomFieldValue("$Severity", buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "critical", result) + + result, err = integration.evaluateCustomFieldValue("$Host", buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "example.com", result) + }) + + t.Run("complex template with conditionals", func(t *testing.T) { + templateStr := `{{.Name}} on {{.Host}} +{{if .CVSSScore}}CVSS: {{.CVSSScore}}{{end}} +{{if eq .Severity "critical"}}⚠️ CRITICAL{{else}}Standard{{end}}` + result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event) + require.NoError(t, err) + require.Contains(t, result, "Test Vulnerability on example.com") + require.Contains(t, result, "CVSS: 9.80") + require.Contains(t, result, "⚠️ CRITICAL") + }) + + t.Run("no template syntax", func(t *testing.T) { + result, err := integration.evaluateCustomFieldValue("plain text", buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "plain text", result) + }) +} From f460bf926d24d8f0e817065769145cfb7846c7a3 Mon Sep 17 00:00:00 2001 From: Ice3man Date: Wed, 10 Sep 2025 17:32:43 +0530 Subject: [PATCH 111/135] feat: added additional text/template helpers --- pkg/reporting/trackers/jira/jira.go | 19 ++++++- pkg/reporting/trackers/jira/jira_test.go | 63 ++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/pkg/reporting/trackers/jira/jira.go b/pkg/reporting/trackers/jira/jira.go index 5e8d45bff..15ba85657 100644 --- a/pkg/reporting/trackers/jira/jira.go +++ b/pkg/reporting/trackers/jira/jira.go @@ -13,6 +13,8 @@ import ( "github.com/andygrunwald/go-jira" "github.com/pkg/errors" "github.com/trivago/tgo/tcontainer" + "golang.org/x/text/cases" + "golang.org/x/text/language" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/output" @@ -67,7 +69,22 @@ func evaluateTemplate(templateStr string, ctx *TemplateContext) (string, error) return templateStr, nil } - tmpl, err := template.New("field").Parse(templateStr) + // Create template with useful functions for JIRA custom fields + funcMap := template.FuncMap{ + "upper": strings.ToUpper, + "lower": strings.ToLower, + "title": cases.Title(language.English).String, + "contains": strings.Contains, + "hasPrefix": strings.HasPrefix, + "hasSuffix": strings.HasSuffix, + "trim": strings.Trim, + "trimSpace": strings.TrimSpace, + "replace": strings.ReplaceAll, + "split": strings.Split, + "join": strings.Join, + } + + tmpl, err := template.New("field").Funcs(funcMap).Parse(templateStr) if err != nil { return templateStr, fmt.Errorf("failed to parse template: %w", err) } diff --git a/pkg/reporting/trackers/jira/jira_test.go b/pkg/reporting/trackers/jira/jira_test.go index 49ae365e6..d9b27adf7 100644 --- a/pkg/reporting/trackers/jira/jira_test.go +++ b/pkg/reporting/trackers/jira/jira_test.go @@ -76,7 +76,7 @@ func TestTemplateEvaluation(t *testing.T) { event := &output.ResultEvent{ Host: "example.com", Info: model.Info{ - Name: "Test Vulnerability", + Name: "Test vulnerability", SeverityHolder: severity.Holder{Severity: severity.Critical}, Classification: &model.Classification{ CVSSScore: 9.8, @@ -100,7 +100,7 @@ func TestTemplateEvaluation(t *testing.T) { templateStr := `Vulnerability detected by Nuclei. Name: {{.Name}}, Severity: {{.Severity}}, Host: {{.Host}}` result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event) require.NoError(t, err) - expected := "Vulnerability detected by Nuclei. Name: Test Vulnerability, Severity: critical, Host: example.com" + expected := "Vulnerability detected by Nuclei. Name: Test vulnerability, Severity: critical, Host: example.com" require.Equal(t, expected, result) }) @@ -120,7 +120,7 @@ func TestTemplateEvaluation(t *testing.T) { {{if eq .Severity "critical"}}⚠️ CRITICAL{{else}}Standard{{end}}` result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event) require.NoError(t, err) - require.Contains(t, result, "Test Vulnerability on example.com") + require.Contains(t, result, "Test vulnerability on example.com") require.Contains(t, result, "CVSS: 9.80") require.Contains(t, result, "⚠️ CRITICAL") }) @@ -130,4 +130,61 @@ func TestTemplateEvaluation(t *testing.T) { require.NoError(t, err) require.Equal(t, "plain text", result) }) + + t.Run("template functions", func(t *testing.T) { + // Test case conversion functions + result, err := integration.evaluateCustomFieldValue("{{.Severity | upper}}", buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "CRITICAL", result) + + result, err = integration.evaluateCustomFieldValue("{{.Name | lower}}", buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "test vulnerability", result) + + result, err = integration.evaluateCustomFieldValue("{{.Name | title}}", buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "Test Vulnerability", result) + + // Test string check functions + result, err = integration.evaluateCustomFieldValue(`{{if contains .Name "Test"}}has-test{{else}}no-test{{end}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "has-test", result) + + result, err = integration.evaluateCustomFieldValue(`{{if hasPrefix .Host "example"}}starts-with-example{{else}}other{{end}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "starts-with-example", result) + + result, err = integration.evaluateCustomFieldValue(`{{if hasSuffix .Host ".com"}}ends-with-com{{else}}other{{end}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "ends-with-com", result) + + // Test string manipulation functions + result, err = integration.evaluateCustomFieldValue(`{{replace .Name " " "-"}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "Test-vulnerability", result) + + result, err = integration.evaluateCustomFieldValue(`{{trimSpace " test "}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "test", result) + + result, err = integration.evaluateCustomFieldValue(`{{trim "...test..." "."}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "test", result) + + // Test split and join functions + result, err = integration.evaluateCustomFieldValue(`{{join (split .Name " ") "-"}}`, buildTemplateContext(event), event) + require.NoError(t, err) + require.Equal(t, "Test-vulnerability", result) + }) + + t.Run("complex template with functions", func(t *testing.T) { + templateStr := `{{.Name | upper}} on {{.Host}} +{{if contains .Name "SQL"}}SQL-INJECTION{{else if contains .Name "XSS"}}XSS-ATTACK{{else}}OTHER{{end}} +Priority: {{if eq .Severity "critical"}}{{.Severity | upper}}{{else}}{{.Severity}}{{end}}` + result, err := integration.evaluateCustomFieldValue(templateStr, buildTemplateContext(event), event) + require.NoError(t, err) + require.Contains(t, result, "TEST VULNERABILITY on example.com", result) + require.Contains(t, result, "OTHER") + require.Contains(t, result, "CRITICAL") + }) } From 4916cf34f0083e0dc874ff969771ce15ced4acef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Wed, 10 Sep 2025 16:44:12 +0300 Subject: [PATCH 112/135] dont load templates with the same ID --- pkg/catalog/loader/loader.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index cfaf4e832..966486b22 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -7,6 +7,7 @@ import ( "os" "sort" "strings" + "sync" "github.com/logrusorgru/aurora" "github.com/pkg/errors" @@ -315,6 +316,8 @@ func (store *Store) LoadTemplatesOnlyMetadata() error { } templatesCache := parserItem.Cache() + loadedTemplateIDs := make(map[string]bool) + for templatePath := range validPaths { template, _, _ := templatesCache.Has(templatePath) @@ -339,6 +342,12 @@ func (store *Store) LoadTemplatesOnlyMetadata() error { } if template != nil { + if loadedTemplateIDs[template.ID] { + store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", template.ID, templatePath) + continue + } + + loadedTemplateIDs[template.ID] = true template.Path = templatePath store.templates = append(store.templates, template) } @@ -492,8 +501,20 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ templatePathMap := store.pathFilter.Match(includedTemplates) loadedTemplates := sliceutil.NewSyncSlice[*templates.Template]() + loadedTemplateIDs := make(map[string]bool) + var loadedTemplateIDsMutex sync.Mutex loadTemplate := func(tmpl *templates.Template) { + loadedTemplateIDsMutex.Lock() + if loadedTemplateIDs[tmpl.ID] { + loadedTemplateIDsMutex.Unlock() + store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", tmpl.ID, tmpl.Path) + return + } + + loadedTemplateIDs[tmpl.ID] = true + loadedTemplateIDsMutex.Unlock() + loadedTemplates.Append(tmpl) // increment signed/unsigned counters if tmpl.Verified { From b05359bc82a96d22989e7a69d4439ed93c145e51 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Wed, 10 Sep 2025 19:48:36 +0200 Subject: [PATCH 113/135] using synclockmap --- pkg/catalog/loader/loader.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 966486b22..79105bfbf 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -7,7 +7,6 @@ import ( "os" "sort" "strings" - "sync" "github.com/logrusorgru/aurora" "github.com/pkg/errors" @@ -26,6 +25,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/workflows" "github.com/projectdiscovery/retryablehttp-go" "github.com/projectdiscovery/utils/errkit" + mapsutil "github.com/projectdiscovery/utils/maps" sliceutil "github.com/projectdiscovery/utils/slice" stringsutil "github.com/projectdiscovery/utils/strings" syncutil "github.com/projectdiscovery/utils/sync" @@ -316,7 +316,7 @@ func (store *Store) LoadTemplatesOnlyMetadata() error { } templatesCache := parserItem.Cache() - loadedTemplateIDs := make(map[string]bool) + loadedTemplateIDs := mapsutil.NewSyncLockMap[string, struct{}]() for templatePath := range validPaths { template, _, _ := templatesCache.Has(templatePath) @@ -342,12 +342,12 @@ func (store *Store) LoadTemplatesOnlyMetadata() error { } if template != nil { - if loadedTemplateIDs[template.ID] { + if loadedTemplateIDs.Has(template.ID) { store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", template.ID, templatePath) continue } - loadedTemplateIDs[template.ID] = true + loadedTemplateIDs.Set(template.ID, struct{}{}) template.Path = templatePath store.templates = append(store.templates, template) } @@ -501,19 +501,15 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ templatePathMap := store.pathFilter.Match(includedTemplates) loadedTemplates := sliceutil.NewSyncSlice[*templates.Template]() - loadedTemplateIDs := make(map[string]bool) - var loadedTemplateIDsMutex sync.Mutex + loadedTemplateIDs := mapsutil.NewSyncLockMap[string, struct{}]() loadTemplate := func(tmpl *templates.Template) { - loadedTemplateIDsMutex.Lock() - if loadedTemplateIDs[tmpl.ID] { - loadedTemplateIDsMutex.Unlock() + if loadedTemplateIDs.Has(tmpl.ID) { store.logger.Debug().Msgf("Skipping duplicate template ID '%s' from path '%s'", tmpl.ID, tmpl.Path) return } - loadedTemplateIDs[tmpl.ID] = true - loadedTemplateIDsMutex.Unlock() + loadedTemplateIDs.Set(tmpl.ID, struct{}{}) loadedTemplates.Append(tmpl) // increment signed/unsigned counters From 608159bbbe92e2c74977180c34893c511721760c Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Wed, 10 Sep 2025 19:53:23 +0200 Subject: [PATCH 114/135] lint --- pkg/catalog/loader/loader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 79105bfbf..40fbaa482 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -347,7 +347,7 @@ func (store *Store) LoadTemplatesOnlyMetadata() error { continue } - loadedTemplateIDs.Set(template.ID, struct{}{}) + _ = loadedTemplateIDs.Set(template.ID, struct{}{}) template.Path = templatePath store.templates = append(store.templates, template) } @@ -509,7 +509,7 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ return } - loadedTemplateIDs.Set(tmpl.ID, struct{}{}) + _ = loadedTemplateIDs.Set(tmpl.ID, struct{}{}) loadedTemplates.Append(tmpl) // increment signed/unsigned counters From c487e596021792596f76a38ba46105dc56be25d6 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 11 Sep 2025 21:41:59 +0200 Subject: [PATCH 115/135] lint --- cmd/nuclei/main.go | 4 +++- pkg/input/formats/yaml/multidoc_test.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/nuclei/main.go b/cmd/nuclei/main.go index 021d75d6a..c08f52bfb 100644 --- a/cmd/nuclei/main.go +++ b/cmd/nuclei/main.go @@ -590,7 +590,9 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started if err != nil { gologger.Fatal().Msgf("Could not open config file: %s\n", err) } - defer file.Close() + defer func() { + _ = file.Close() + }() data := make(map[string]interface{}) err = yaml.NewDecoder(file).Decode(&data) if err != nil { diff --git a/pkg/input/formats/yaml/multidoc_test.go b/pkg/input/formats/yaml/multidoc_test.go index 54efe0326..40d078a0a 100644 --- a/pkg/input/formats/yaml/multidoc_test.go +++ b/pkg/input/formats/yaml/multidoc_test.go @@ -53,7 +53,9 @@ func TestYamlFormatterParseWithVariables(t *testing.T) { }) file, err := os.Open(proxifyYttFile) require.Nilf(t, err, "error opening proxify ytt input file: %v", err) - defer file.Close() + defer func() { + _ = file.Close() + }() var urls []string err = format.Parse(file, func(request *types.RequestResponse) bool { From ee1c847626c210c832f4249b26ecb9cc89248b35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 05:02:07 +0000 Subject: [PATCH 116/135] chore(deps): bump the modules group with 9 updates Bumps the modules group with 9 updates: | Package | From | To | | --- | --- | --- | | [github.com/projectdiscovery/fastdialer](https://github.com/projectdiscovery/fastdialer) | `0.4.7` | `0.4.9` | | [github.com/projectdiscovery/retryabledns](https://github.com/projectdiscovery/retryabledns) | `1.0.106` | `1.0.107` | | [github.com/projectdiscovery/retryablehttp-go](https://github.com/projectdiscovery/retryablehttp-go) | `1.0.121` | `1.0.123` | | [github.com/projectdiscovery/dsl](https://github.com/projectdiscovery/dsl) | `0.5.1` | `0.6.0` | | [github.com/projectdiscovery/httpx](https://github.com/projectdiscovery/httpx) | `1.7.1-0.20250902174407-8d6c2658663f` | `1.7.1` | | [github.com/projectdiscovery/networkpolicy](https://github.com/projectdiscovery/networkpolicy) | `0.1.21` | `0.1.23` | | [github.com/projectdiscovery/utils](https://github.com/projectdiscovery/utils) | `0.4.24-0.20250823123502-bd7f2849ddb4` | `0.5.0` | | [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) | `0.2.43` | `0.2.45` | | [github.com/projectdiscovery/cdncheck](https://github.com/projectdiscovery/cdncheck) | `1.1.33` | `1.1.35` | Updates `github.com/projectdiscovery/fastdialer` from 0.4.7 to 0.4.9 - [Release notes](https://github.com/projectdiscovery/fastdialer/releases) - [Commits](https://github.com/projectdiscovery/fastdialer/compare/v0.4.7...v0.4.9) Updates `github.com/projectdiscovery/retryabledns` from 1.0.106 to 1.0.107 - [Release notes](https://github.com/projectdiscovery/retryabledns/releases) - [Commits](https://github.com/projectdiscovery/retryabledns/compare/v1.0.106...v1.0.107) Updates `github.com/projectdiscovery/retryablehttp-go` from 1.0.121 to 1.0.123 - [Release notes](https://github.com/projectdiscovery/retryablehttp-go/releases) - [Commits](https://github.com/projectdiscovery/retryablehttp-go/compare/v1.0.121...v1.0.123) Updates `github.com/projectdiscovery/dsl` from 0.5.1 to 0.6.0 - [Release notes](https://github.com/projectdiscovery/dsl/releases) - [Commits](https://github.com/projectdiscovery/dsl/compare/v0.5.1...v0.6.0) Updates `github.com/projectdiscovery/httpx` from 1.7.1-0.20250902174407-8d6c2658663f to 1.7.1 - [Release notes](https://github.com/projectdiscovery/httpx/releases) - [Changelog](https://github.com/projectdiscovery/httpx/blob/dev/.goreleaser.yml) - [Commits](https://github.com/projectdiscovery/httpx/commits/v1.7.1) Updates `github.com/projectdiscovery/networkpolicy` from 0.1.21 to 0.1.23 - [Release notes](https://github.com/projectdiscovery/networkpolicy/releases) - [Commits](https://github.com/projectdiscovery/networkpolicy/compare/v0.1.21...v0.1.23) Updates `github.com/projectdiscovery/utils` from 0.4.24-0.20250823123502-bd7f2849ddb4 to 0.5.0 - [Release notes](https://github.com/projectdiscovery/utils/releases) - [Changelog](https://github.com/projectdiscovery/utils/blob/main/CHANGELOG.md) - [Commits](https://github.com/projectdiscovery/utils/commits/v0.5.0) Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.43 to 0.2.45 - [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases) - [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.43...v0.2.45) Updates `github.com/projectdiscovery/cdncheck` from 1.1.33 to 1.1.35 - [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.33...v1.1.35) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/fastdialer dependency-version: 0.4.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/retryabledns dependency-version: 1.0.107 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/retryablehttp-go dependency-version: 1.0.123 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/dsl dependency-version: 0.6.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: modules - dependency-name: github.com/projectdiscovery/httpx dependency-version: 1.7.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/networkpolicy dependency-version: 0.1.23 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/utils dependency-version: 0.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: modules - dependency-name: github.com/projectdiscovery/wappalyzergo dependency-version: 0.2.45 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/cdncheck dependency-version: 1.1.35 dependency-type: indirect update-type: version-update:semver-patch dependency-group: modules ... Signed-off-by: dependabot[bot] --- go.mod | 22 +++++++++++----------- go.sum | 44 ++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index 62f9ad0c4..95d0d9ac5 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,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.7 + github.com/projectdiscovery/fastdialer v0.4.9 github.com/projectdiscovery/hmap v0.0.93 github.com/projectdiscovery/interactsh v1.2.4 github.com/projectdiscovery/rawhttp v0.1.90 - github.com/projectdiscovery/retryabledns v1.0.106 - github.com/projectdiscovery/retryablehttp-go v1.0.121 + github.com/projectdiscovery/retryabledns v1.0.107 + github.com/projectdiscovery/retryablehttp-go v1.0.123 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.0 @@ -90,7 +90,7 @@ require ( github.com/microsoft/go-mssqldb v1.9.2 github.com/ory/dockertest/v3 v3.12.0 github.com/praetorian-inc/fingerprintx v1.1.15 - github.com/projectdiscovery/dsl v0.5.1 + github.com/projectdiscovery/dsl v0.6.0 github.com/projectdiscovery/fasttemplate v0.0.2 github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb @@ -98,22 +98,22 @@ require ( github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/gostruct v0.0.2 github.com/projectdiscovery/gozero v0.1.0 - github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f + github.com/projectdiscovery/httpx v1.7.1 github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 - github.com/projectdiscovery/networkpolicy v0.1.21 + github.com/projectdiscovery/networkpolicy v0.1.23 github.com/projectdiscovery/ratelimit v0.0.82 github.com/projectdiscovery/rdap v0.9.0 github.com/projectdiscovery/sarif v0.0.1 github.com/projectdiscovery/tlsx v1.2.1 github.com/projectdiscovery/uncover v1.1.0 github.com/projectdiscovery/useragent v0.0.101 - github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4 - github.com/projectdiscovery/wappalyzergo v0.2.43 + github.com/projectdiscovery/utils v0.5.0 + github.com/projectdiscovery/wappalyzergo v0.2.45 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 - github.com/stretchr/testify v1.11.0 + github.com/stretchr/testify v1.11.1 github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 github.com/testcontainers/testcontainers-go v0.38.0 github.com/testcontainers/testcontainers-go/modules/mongodb v0.37.0 @@ -315,7 +315,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.33 // indirect + github.com/projectdiscovery/cdncheck v1.1.35 // indirect 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 @@ -341,7 +341,7 @@ require ( github.com/tklauser/numcpus v0.10.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect - github.com/ulikunitz/xz v0.5.12 // indirect + github.com/ulikunitz/xz v0.5.14 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect diff --git a/go.sum b/go.sum index deb089746..e69b6122d 100644 --- a/go.sum +++ b/go.sum @@ -1245,14 +1245,14 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.33 h1:xQYq+ms0yaLaiK1BbfNc9pKsrnYVLhwRMF4yJWNfMn4= -github.com/projectdiscovery/cdncheck v1.1.33/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.35 h1:xyMnIWf2wzKH4Ii3lBNb73b/n9ee/baEiS3Ao23pyco= +github.com/projectdiscovery/cdncheck v1.1.35/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= -github.com/projectdiscovery/dsl v0.5.1 h1:Nm6ToWtNKrhrF880qWykbub60Lw4m96ZkB43OGOsVLg= -github.com/projectdiscovery/dsl v0.5.1/go.mod h1:m+tLImvmlEnFTuwb0Bm3DqCL6e7sWOunJyxFi27AduI= -github.com/projectdiscovery/fastdialer v0.4.7 h1:fErLAppGZtZMGLLyeInMh4Kw/N0FXlTVh35v07dpS7I= -github.com/projectdiscovery/fastdialer v0.4.7/go.mod h1:0Nm8GgU3Ds2Ac3/Fg59mVG40eMFYNA426PAcYqeNioM= +github.com/projectdiscovery/dsl v0.6.0 h1:j4T6WKDx7uuhCSYjvEAySn86G7tTeEEsMeqjUauuqss= +github.com/projectdiscovery/dsl v0.6.0/go.mod h1:m+tLImvmlEnFTuwb0Bm3DqCL6e7sWOunJyxFi27AduI= +github.com/projectdiscovery/fastdialer v0.4.9 h1:/CTzoEsayQOrYJjB0CCa/0iNX7LSMeml6XmeyxX8ZVA= +github.com/projectdiscovery/fastdialer v0.4.9/go.mod h1:/4f7ELi6M5sr5XOpt+q0OpP4sQV36f3bOG23n7GOQUw= 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= @@ -1271,8 +1271,8 @@ github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mna github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs= github.com/projectdiscovery/hmap v0.0.93 h1:iIRdioT4byGJ4Hz5cOjo1fd3HFFi1MUFPv+EGYc1yng= github.com/projectdiscovery/hmap v0.0.93/go.mod h1:oKgtWo2QMD7BkW25ezYbFCqKO3IctZ2ByEaG2XWW0t0= -github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f h1:Z73qF1ilD5RUsZP4Px4JImFkCTRlQ5K8uR2gm9eakw8= -github.com/projectdiscovery/httpx v1.7.1-0.20250902174407-8d6c2658663f/go.mod h1:hGAOnHyiq80ASpwbycv8Q32wsfcI8xtADEDw/mKPqTs= +github.com/projectdiscovery/httpx v1.7.1 h1:XmhUGGUdmpWWXyQC8utV9gyHVrjzXBcT2SAUOgFOQV8= +github.com/projectdiscovery/httpx v1.7.1/go.mod h1:fejxELITLvQ0uXB/pnBiekjMmGdoE7+7p+DpIYhAhJU= github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI= github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc= github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8= @@ -1283,18 +1283,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.21 h1:BOlYxPyrfqb5DneyuokZkRpeX5MCXLjCH4sI2hLudII= -github.com/projectdiscovery/networkpolicy v0.1.21/go.mod h1:/DI9DZANBQ20x09mvcHA0J/3dCLBgCkEW5r5/L1b87U= +github.com/projectdiscovery/networkpolicy v0.1.23 h1:+MVm9xHCfzmZG5WhUtjAGFvNiQNKOgxZDDed1QfpLXI= +github.com/projectdiscovery/networkpolicy v0.1.23/go.mod h1:ILun9d4jgAfLOYf/NYjV+sKyW3tZTLMl+HyvaZuXZo0= github.com/projectdiscovery/ratelimit v0.0.82 h1:rtO5SQf5uQFu5zTahTaTcO06OxmG8EIF1qhdFPIyTak= github.com/projectdiscovery/ratelimit v0.0.82/go.mod h1:z076BrLkBb5yS7uhHNoCTf8X/BvFSGRxwQ8EzEL9afM= 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.106 h1:repm5aGq5ge6fNJQbPNux7vyUhtUju7aIMEXZD9FX0A= -github.com/projectdiscovery/retryabledns v1.0.106/go.mod h1:1W3ogENvt3Pb+Ju4AN0aE2lZy+D76Yzxsz51DqFCIk8= -github.com/projectdiscovery/retryablehttp-go v1.0.121 h1:KQcMS7z5k3xnrTnD5G+HOVp1YRIbaB/iA+moc2lkR4c= -github.com/projectdiscovery/retryablehttp-go v1.0.121/go.mod h1:15Usp6eLzNM/mI/jd+ucYRiyUuvm7vg2ymWRylG/Zss= +github.com/projectdiscovery/retryabledns v1.0.107 h1:Rd1JK7hfL68xRg3RzXmw9Q6B6WSNv9bdPhUoGvvebyg= +github.com/projectdiscovery/retryabledns v1.0.107/go.mod h1:XddeOhDpwS0qR8/T4GXRGgDQsLhtRHw3TRdMsgJs28o= +github.com/projectdiscovery/retryablehttp-go v1.0.123 h1:jnbNlYJ64ScyMIiPNpyXXX7fVpOfoII20knO2xHH+4s= +github.com/projectdiscovery/retryablehttp-go v1.0.123/go.mod h1:lv7L70Q/Lc+LARjk6ji+Ihd4Bjb9c/qmqLcdCH8Gzbo= 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= @@ -1305,10 +1305,10 @@ 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.24-0.20250823123502-bd7f2849ddb4 h1:qQMEhfxDsiZ+Ay3dj93FuMAa7yt1XE2bxDpPSTEz/P0= -github.com/projectdiscovery/utils v0.4.24-0.20250823123502-bd7f2849ddb4/go.mod h1:ipzU2PHYP71MaMn4jllPOpdYpdMkFD0jE3Tjak4b4eM= -github.com/projectdiscovery/wappalyzergo v0.2.43 h1:gmjBJv2xHFBl48B0yFe2OL6v+mXe4KMLNdEmuMpqfhk= -github.com/projectdiscovery/wappalyzergo v0.2.43/go.mod h1:N2ZzJYLz1FEyLO4oIL0scz8Z/r2eRRylKFrt3Zy25tc= +github.com/projectdiscovery/utils v0.5.0 h1:DN7mg2DpyObLByuObXzAFEkdNRDoPUnqE5N2szd3b3c= +github.com/projectdiscovery/utils v0.5.0/go.mod h1:eCAWMmyaNxyPWbiKv1oeYJLIKpxceHE2+NWx3Jodhqk= +github.com/projectdiscovery/wappalyzergo v0.2.45 h1:tx0UuYw9GjDy/FMLsL9mr3HjPXoa3qS/lFnda/zQvf4= +github.com/projectdiscovery/wappalyzergo v0.2.45/go.mod h1:1dHfTJRhrbbWBdKwl1p4QKpUDNnPYlHBBL7rEwCDdjM= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1427,8 +1427,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= -github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/substrait-io/substrait-go v0.4.2/go.mod h1:qhpnLmrcvAnlZsUyPXZRqldiHapPTXC3t7xFgDi3aQg= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= @@ -1477,8 +1477,8 @@ github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= -github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= +github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= From 94c77c1a28b824ae76cae968ec396f1380da9103 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 11 Sep 2025 21:23:46 +0200 Subject: [PATCH 117/135] httpx fix --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 95d0d9ac5..1aec11943 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( go.uber.org/multierr v1.11.0 golang.org/x/net v0.43.0 golang.org/x/oauth2 v0.30.0 - golang.org/x/text v0.28.0 + golang.org/x/text v0.29.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -98,7 +98,7 @@ require ( github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/gostruct v0.0.2 github.com/projectdiscovery/gozero v0.1.0 - github.com/projectdiscovery/httpx v1.7.1 + github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 github.com/projectdiscovery/networkpolicy v0.1.23 @@ -355,7 +355,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/ysmood/fetchup v0.2.3 // indirect github.com/ysmood/got v0.40.0 // indirect - github.com/yuin/goldmark v1.7.11 // indirect + github.com/yuin/goldmark v1.7.13 // indirect github.com/yuin/goldmark-emoji v1.0.5 // indirect github.com/zcalusic/sysinfo v1.0.2 // indirect github.com/zeebo/blake3 v0.2.3 // indirect @@ -366,7 +366,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/sync v0.16.0 // indirect + golang.org/x/sync v0.17.0 // indirect gopkg.in/djherbis/times.v1 v1.3.0 // indirect mellium.im/sasl v0.3.2 // indirect ) @@ -392,10 +392,10 @@ require ( goftp.io/server/v2 v2.0.1 // indirect golang.org/x/crypto v0.41.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b - golang.org/x/mod v0.26.0 // indirect + golang.org/x/mod v0.27.0 // indirect golang.org/x/sys v0.35.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.35.0 + golang.org/x/tools v0.36.0 google.golang.org/protobuf v1.36.6 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect diff --git a/go.sum b/go.sum index e69b6122d..dab91a511 100644 --- a/go.sum +++ b/go.sum @@ -1271,8 +1271,8 @@ github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mna github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs= github.com/projectdiscovery/hmap v0.0.93 h1:iIRdioT4byGJ4Hz5cOjo1fd3HFFi1MUFPv+EGYc1yng= github.com/projectdiscovery/hmap v0.0.93/go.mod h1:oKgtWo2QMD7BkW25ezYbFCqKO3IctZ2ByEaG2XWW0t0= -github.com/projectdiscovery/httpx v1.7.1 h1:XmhUGGUdmpWWXyQC8utV9gyHVrjzXBcT2SAUOgFOQV8= -github.com/projectdiscovery/httpx v1.7.1/go.mod h1:fejxELITLvQ0uXB/pnBiekjMmGdoE7+7p+DpIYhAhJU= +github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a h1:5NBp4BegAQuT3QSnbBKt05LH1nOyEeFAXYh1+aE3Nlo= +github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a/go.mod h1:SQl92RiEuBnv1QQ8aQLC3b1lfgGHttoqUV0cTTvlzxQ= github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI= github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc= github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8= @@ -1543,8 +1543,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo= -github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= +github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk= github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= @@ -1759,8 +1759,8 @@ golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1910,8 +1910,8 @@ golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2084,8 +2084,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2163,8 +2163,8 @@ golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 4b22a3d53eda312843c6617cc93747661c15397c Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Thu, 11 Sep 2025 22:13:09 +0200 Subject: [PATCH 118/135] release fix --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1aec11943..1c1045470 100644 --- a/go.mod +++ b/go.mod @@ -341,7 +341,7 @@ require ( github.com/tklauser/numcpus v0.10.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect - github.com/ulikunitz/xz v0.5.14 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect diff --git a/go.sum b/go.sum index dab91a511..11dadf023 100644 --- a/go.sum +++ b/go.sum @@ -1477,8 +1477,8 @@ github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= -github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= From 5c8da8d88bde43de2fc6fc5214820705f2b34377 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 12 Sep 2025 10:29:42 +0200 Subject: [PATCH 119/135] code from https://github.com/projectdiscovery/nuclei/pull/6427 --- cmd/integration-test/javascript.go | 61 +++++++- pkg/js/generated/go/liboracle/oracle.go | 1 + pkg/js/generated/ts/oracle.ts | 109 +++++++++++--- pkg/js/libs/oracle/oracle.go | 141 +++++++++++++++++- pkg/js/libs/oracle/oracledialer.go | 42 ++++++ .../testcases/oracle-auth-test.yaml | 29 ++++ 6 files changed, 360 insertions(+), 23 deletions(-) create mode 100644 pkg/js/libs/oracle/oracledialer.go create mode 100644 pkg/protocols/javascript/testcases/oracle-auth-test.yaml diff --git a/cmd/integration-test/javascript.go b/cmd/integration-test/javascript.go index e45f122c3..61516abd2 100644 --- a/cmd/integration-test/javascript.go +++ b/cmd/integration-test/javascript.go @@ -15,13 +15,15 @@ var jsTestcases = []TestCaseInfo{ {Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, {Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}}, {Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNetHttps{}}, + {Path: "protocols/javascript/oracle-auth-test.yaml", TestCase: &javascriptOracleAuthTest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, } var ( - redisResource *dockertest.Resource - sshResource *dockertest.Resource - pool *dockertest.Pool - defaultRetry = 3 + redisResource *dockertest.Resource + sshResource *dockertest.Resource + oracleResource *dockertest.Resource + pool *dockertest.Pool + defaultRetry = 3 ) type javascriptNetHttps struct{} @@ -98,6 +100,38 @@ func (j *javascriptSSHServerFingerprint) Execute(filePath string) error { return multierr.Combine(errs...) } +type javascriptOracleAuthTest struct{} + +func (j *javascriptOracleAuthTest) Execute(filePath string) error { + if oracleResource == nil || pool == nil { + // skip test as oracle is not running + return nil + } + tempPort := oracleResource.GetPort("1521/tcp") + finalURL := "localhost:" + tempPort + defer purge(oracleResource) + errs := []error{} + for i := 0; i < defaultRetry; i++ { + results := []string{} + var err error + _ = pool.Retry(func() error { + //let ssh server start + time.Sleep(3 * time.Second) + results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug) + return nil + }) + if err != nil { + return err + } + if err := expectResultsCount(results, 1); err == nil { + return nil + } else { + errs = append(errs, err) + } + } + return multierr.Combine(errs...) +} + // purge any given resource if it is not nil func purge(resource *dockertest.Resource) { if resource != nil && pool != nil { @@ -163,4 +197,23 @@ func init() { if err := sshResource.Expire(30); err != nil { log.Printf("Could not expire resource: %s", err) } + + // setup a temporary oracle instance + oracleResource, err = pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "gvenzl/oracle-xe", + Tag: "latest", + Env: []string{ + "ORACLE_PASSWORD=mysecret", + }, + Platform: "linux/amd64", + }) + if err != nil { + log.Printf("Could not start Oracle resource: %s", err) + return + } + + // by default expire after 30 sec + if err := oracleResource.Expire(30); err != nil { + log.Printf("Could not expire Oracle resource: %s", err) + } } diff --git a/pkg/js/generated/go/liboracle/oracle.go b/pkg/js/generated/go/liboracle/oracle.go index 67110b4c8..7558adc42 100644 --- a/pkg/js/generated/go/liboracle/oracle.go +++ b/pkg/js/generated/go/liboracle/oracle.go @@ -21,6 +21,7 @@ func init() { // Objects / Classes "IsOracleResponse": gojs.GetClassConstructor[lib_oracle.IsOracleResponse](&lib_oracle.IsOracleResponse{}), + "OracleClient": gojs.GetClassConstructor[lib_oracle.OracleClient](&lib_oracle.OracleClient{}), }, ).Register() } diff --git a/pkg/js/generated/ts/oracle.ts b/pkg/js/generated/ts/oracle.ts index 852e919e7..5701a4c51 100755 --- a/pkg/js/generated/ts/oracle.ts +++ b/pkg/js/generated/ts/oracle.ts @@ -1,33 +1,106 @@ -/** - * IsOracle checks if a host is running an Oracle server - * @example - * ```javascript - * const oracle = require('nuclei/oracle'); - * const isOracle = oracle.IsOracle('acme.com', 1521); - * log(toJSON(isOracle)); - * ``` - */ -export function IsOracle(host: string, port: number): IsOracleResponse | null { - return null; -} - - - /** * IsOracleResponse is the response from the IsOracle function. * this is returned by IsOracle function. * @example * ```javascript * const oracle = require('nuclei/oracle'); - * const isOracle = oracle.IsOracle('acme.com', 1521); + * const client = new oracle.OracleClient(); + * const isOracle = client.IsOracle('acme.com', 1521); * ``` */ export interface IsOracleResponse { - IsOracle?: boolean, - Banner?: string, } +/** + * Client is a client for Oracle database. + * Internally client uses go-ora driver. + * @example + * ```javascript + * const oracle = require('nuclei/oracle'); + * const client = new oracle.OracleClient(); + * ``` + */ +export class OracleClient { + // Constructor of OracleClient + constructor() {} + + /** + * Connect connects to an Oracle database + * @example + * ```javascript + * const oracle = require('nuclei/oracle'); + * const client = new oracle.OracleClient(); + * client.Connect('acme.com', 1521, 'XE', 'user', 'password'); + * ``` + */ + public Connect(host: string, port: number, serviceName: string, username: string, password: string): boolean | null { + return null; + } + + /** + * ConnectWithDSN connects to an Oracle database using a DSN string + * @example + * ```javascript + * const oracle = require('nuclei/oracle'); + * const client = new oracle.OracleClient(); + * client.ConnectWithDSN('oracle://user:password@host:port/service', 'SELECT @@version'); + * ``` + */ + public ConnectWithDSN(dsn: string): boolean | null { + return null; + } + + /** + * IsOracle checks if a host is running an Oracle server + * @example + * ```javascript + * const oracle = require('nuclei/oracle'); + * const isOracle = oracle.IsOracle('acme.com', 1521); + * ``` + */ + public IsOracle(host: string, port: number): IsOracleResponse | null { + return null; + } + + /** + * ExecuteQuery connects to Oracle database using given credentials and executes a query. + * It returns the results of the query or an error if something goes wrong. + * @example + * ```javascript + * const oracle = require('nuclei/oracle'); + * const client = new oracle.OracleClient(); + * const result = client.ExecuteQuery('acme.com', 1521, 'username', 'password', 'XE', 'SELECT * FROM dual'); + * log(to_json(result)); + * ``` + */ + public ExecuteQuery(host: string, port: number, username: string, password: string, dbName: string, query: string): SQLResult | null { + return null; + } + + /** + * ExecuteQueryWithDSN executes a query on an Oracle database using a DSN + * @example + * ```javascript + * const oracle = require('nuclei/oracle'); + * const client = new oracle.OracleClient(); + * const result = client.ExecuteQueryWithDSN('oracle://user:password@host:port/service', 'SELECT * FROM dual'); + * log(to_json(result)); + * ``` + */ + public ExecuteQueryWithDSN(dsn: string, query: string): SQLResult | null { + return null; + } +} + +/** + * SQLResult Interface + */ +export interface SQLResult { + Count?: number, + Columns?: string[], + Rows?: any[], +} diff --git a/pkg/js/libs/oracle/oracle.go b/pkg/js/libs/oracle/oracle.go index 9d4117d85..5a0a3ad05 100644 --- a/pkg/js/libs/oracle/oracle.go +++ b/pkg/js/libs/oracle/oracle.go @@ -2,6 +2,7 @@ package oracle import ( "context" + "database/sql" "fmt" "net" "strconv" @@ -9,7 +10,9 @@ import ( "github.com/praetorian-inc/fingerprintx/pkg/plugins" "github.com/praetorian-inc/fingerprintx/pkg/plugins/services/oracledb" + "github.com/projectdiscovery/nuclei/v3/pkg/js/utils" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" + goora "github.com/sijms/go-ora/v2" ) type ( @@ -24,6 +27,16 @@ type ( IsOracle bool Banner string } + // Client is a client for Oracle database. + // Internally client uses oracle/godror driver. + // @example + // ```javascript + // const oracle = require('nuclei/oracle'); + // const client = new oracle.OracleClient(); + // ``` + OracleClient struct { + connector *goora.OracleConnector + } ) // IsOracle checks if a host is running an Oracle server @@ -33,7 +46,7 @@ type ( // const isOracle = oracle.IsOracle('acme.com', 1521); // log(toJSON(isOracle)); // ``` -func IsOracle(ctx context.Context, host string, port int) (IsOracleResponse, error) { +func (c *OracleClient) IsOracle(ctx context.Context, host string, port int) (IsOracleResponse, error) { executionId := ctx.Value("executionId").(string) return memoizedisOracle(executionId, host, port) } @@ -69,3 +82,129 @@ func isOracle(executionId string, host string, port int) (IsOracleResponse, erro resp.IsOracle = true return resp, nil } + +func (c *OracleClient) oracleDbInstance(connStr string, executionId string) (*goora.OracleConnector, error) { + if c.connector != nil { + return c.connector, nil + } + + connector := goora.NewConnector(connStr) + oraConnector, ok := connector.(*goora.OracleConnector) + if !ok { + return nil, fmt.Errorf("failed to cast connector to OracleConnector") + } + + // Create custom dialer wrapper + customDialer := &oracleCustomDialer{ + executionId: executionId, + } + + oraConnector.Dialer(customDialer) + + c.connector = oraConnector + + return oraConnector, nil +} + +// Connect connects to an Oracle database +// @example +// ```javascript +// const oracle = require('nuclei/oracle'); +// const client = new oracle.OracleClient; +// client.Connect('acme.com', 1521, 'XE', 'user', 'password'); +// ``` +func (c *OracleClient) Connect(ctx context.Context, host string, port int, serviceName string, username string, password string) (bool, error) { + connStr := goora.BuildUrl(host, port, serviceName, username, password, nil) + + return c.ConnectWithDSN(ctx, connStr) +} + +func (c *OracleClient) ConnectWithDSN(ctx context.Context, dsn string) (bool, error) { + executionId := ctx.Value("executionId").(string) + + connector, err := c.oracleDbInstance(dsn, executionId) + if err != nil { + return false, err + } + + db := sql.OpenDB(connector) + defer func() { + _ = db.Close() + }() + + db.SetMaxOpenConns(1) + db.SetMaxIdleConns(0) + + // Test the connection + err = db.Ping() + if err != nil { + return false, err + } + + return true, nil +} + +// ExecuteQuery connects to MS SQL database using given credentials and executes a query. +// It returns the results of the query or an error if something goes wrong. +// @example +// ```javascript +// const oracle = require('nuclei/oracle'); +// const client = new oracle.OracleClient; +// const result = client.ExecuteQuery('acme.com', 1521, 'username', 'password', 'XE', 'SELECT @@version'); +// log(to_json(result)); +// ``` +func (c *OracleClient) ExecuteQuery(ctx context.Context, host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) { + if host == "" || port <= 0 { + return nil, fmt.Errorf("invalid host or port") + } + + isOracleResp, err := c.IsOracle(ctx, host, port) + if err != nil { + return nil, err + } + if !isOracleResp.IsOracle { + return nil, fmt.Errorf("not a oracle service") + } + + connStr := goora.BuildUrl(host, port, dbName, username, password, nil) + + return c.ExecuteQueryWithDSN(ctx, connStr, query) +} + +// ExecuteQueryWithDSN executes a query on an Oracle database using a DSN +// @example +// ```javascript +// const oracle = require('nuclei/oracle'); +// const client = new oracle.OracleClient; +// const result = client.ExecuteQueryWithDSN('oracle://user:password@host:port/service', 'SELECT @@version'); +// log(to_json(result)); +// ``` +func (c *OracleClient) ExecuteQueryWithDSN(ctx context.Context, dsn string, query string) (*utils.SQLResult, error) { + executionId := ctx.Value("executionId").(string) + + connector, err := c.oracleDbInstance(dsn, executionId) + if err != nil { + return nil, err + } + db := sql.OpenDB(connector) + defer func() { + _ = db.Close() + }() + + db.SetMaxOpenConns(1) + db.SetMaxIdleConns(0) + + rows, err := db.Query(query) + if err != nil { + return nil, err + } + + data, err := utils.UnmarshalSQLRows(rows) + if err != nil { + if data != nil && len(data.Rows) > 0 { + return data, nil + } + return nil, err + } + return data, nil +} diff --git a/pkg/js/libs/oracle/oracledialer.go b/pkg/js/libs/oracle/oracledialer.go new file mode 100644 index 000000000..47c62dc13 --- /dev/null +++ b/pkg/js/libs/oracle/oracledialer.go @@ -0,0 +1,42 @@ +package oracle + +import ( + "context" + "fmt" + "net" + "time" + + "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate" +) + +// oracleCustomDialer implements the dialer interface expected by go-ora +type oracleCustomDialer struct { + executionId string +} + +func (o *oracleCustomDialer) dialWithCtx(ctx context.Context, network, address string) (net.Conn, error) { + dialers := protocolstate.GetDialersWithId(o.executionId) + if dialers == nil { + return nil, fmt.Errorf("dialers not initialized for %s", o.executionId) + } + if !protocolstate.IsHostAllowed(o.executionId, address) { + // host is not valid according to network policy + return nil, protocolstate.ErrHostDenied.Msgf(address) + } + return dialers.Fastdialer.Dial(ctx, network, address) +} + +func (o *oracleCustomDialer) Dial(network, address string) (net.Conn, error) { + return o.dialWithCtx(context.TODO(), network, address) +} + +func (o *oracleCustomDialer) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + return o.dialWithCtx(ctx, network, address) +} + +func (o *oracleCustomDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + return o.dialWithCtx(ctx, network, address) +} diff --git a/pkg/protocols/javascript/testcases/oracle-auth-test.yaml b/pkg/protocols/javascript/testcases/oracle-auth-test.yaml new file mode 100644 index 000000000..527bfec6f --- /dev/null +++ b/pkg/protocols/javascript/testcases/oracle-auth-test.yaml @@ -0,0 +1,29 @@ +id: oracle-auth-test + +info: + name: Oracle - Authentication Test + author: pdteam + severity: info + tags: js,oracle,network,auth + +javascript: + - pre-condition: | + isPortOpen(Host,Port); + code: | + let o = require('nuclei/oracle'); + let c = o.OracleClient(); + c.Connect(Host, Port, ServiceName, User, Pass); + + args: + ServiceName: "XE" + Host: "{{Host}}" + Port: "1521" + User: "system" + Pass: "{{passwords}}" + payloads: + passwords: + - mysecret + matchers: + - type: dsl + dsl: + - "response == true" \ No newline at end of file From c8631437712c9adc1fede37c3f6a66f24c9b3bd3 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 12 Sep 2025 10:35:09 +0200 Subject: [PATCH 120/135] lint --- go.mod | 1 + go.sum | 2 ++ pkg/js/generated/go/liboracle/oracle.go | 1 - 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1c1045470..60d4ef093 100644 --- a/go.mod +++ b/go.mod @@ -113,6 +113,7 @@ require ( github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 + github.com/sijms/go-ora/v2 v2.9.0 github.com/stretchr/testify v1.11.1 github.com/tarunKoyalwar/goleak v0.0.0-20240429141123-0efa90dbdcf9 github.com/testcontainers/testcontainers-go v0.38.0 diff --git a/go.sum b/go.sum index 11dadf023..59725b255 100644 --- a/go.sum +++ b/go.sum @@ -1381,6 +1381,8 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= +github.com/sijms/go-ora/v2 v2.9.0 h1:+iQbUeTeCOFMb5BsOMgUhV8KWyrv9yjKpcK4x7+MFrg= +github.com/sijms/go-ora/v2 v2.9.0/go.mod h1:QgFInVi3ZWyqAiJwzBQA+nbKYKH77tdp1PYoCqhR2dU= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= diff --git a/pkg/js/generated/go/liboracle/oracle.go b/pkg/js/generated/go/liboracle/oracle.go index 7558adc42..d579c3474 100644 --- a/pkg/js/generated/go/liboracle/oracle.go +++ b/pkg/js/generated/go/liboracle/oracle.go @@ -15,7 +15,6 @@ func init() { module.Set( gojs.Objects{ // Functions - "IsOracle": lib_oracle.IsOracle, // Var and consts From 089e2a4ee0ff4aa58a46ceeb98a9d50fbfb0e6b5 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 12 Sep 2025 17:46:42 +0200 Subject: [PATCH 121/135] centralizing ratelimiter logic --- internal/runner/runner.go | 6 +----- lib/config.go | 4 ++-- lib/multi.go | 8 ++------ pkg/utils/utils.go | 12 ++++++++++++ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 2a3c2c470..59910f824 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -384,11 +384,7 @@ func New(options *types.Options) (*Runner, error) { if options.RateLimit > 0 && options.RateLimitDuration == 0 { options.RateLimitDuration = time.Second } - if options.RateLimit == 0 && options.RateLimitDuration == 0 { - runner.rateLimiter = ratelimit.NewUnlimited(context.Background()) - } else { - runner.rateLimiter = ratelimit.New(context.Background(), uint(options.RateLimit), options.RateLimitDuration) - } + runner.rateLimiter = utils.GetRateLimiter(context.Background(), options.RateLimit, options.RateLimitDuration) if tmpDir, err := os.MkdirTemp("", "nuclei-tmp-*"); err == nil { runner.tmpDir = tmpDir diff --git a/lib/config.go b/lib/config.go index 2c2a585d9..cdc56ce06 100644 --- a/lib/config.go +++ b/lib/config.go @@ -7,7 +7,7 @@ import ( "github.com/projectdiscovery/goflags" "github.com/projectdiscovery/gologger" - "github.com/projectdiscovery/ratelimit" + "github.com/projectdiscovery/nuclei/v3/pkg/utils" "github.com/projectdiscovery/utils/errkit" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider" @@ -181,7 +181,7 @@ func WithGlobalRateLimitCtx(ctx context.Context, maxTokens int, duration time.Du return func(e *NucleiEngine) error { e.opts.RateLimit = maxTokens e.opts.RateLimitDuration = duration - e.rateLimiter = ratelimit.New(ctx, uint(e.opts.RateLimit), e.opts.RateLimitDuration) + e.rateLimiter = utils.GetRateLimiter(ctx, e.opts.RateLimit, e.opts.RateLimitDuration) return nil } } diff --git a/lib/multi.go b/lib/multi.go index 5c542513c..b6c577587 100644 --- a/lib/multi.go +++ b/lib/multi.go @@ -12,7 +12,7 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/protocols" "github.com/projectdiscovery/nuclei/v3/pkg/types" - "github.com/projectdiscovery/ratelimit" + "github.com/projectdiscovery/nuclei/v3/pkg/utils" "github.com/projectdiscovery/utils/errkit" "github.com/rs/xid" ) @@ -53,11 +53,7 @@ func createEphemeralObjects(ctx context.Context, base *NucleiEngine, opts *types if opts.RateLimit > 0 && opts.RateLimitDuration == 0 { opts.RateLimitDuration = time.Second } - if opts.RateLimit == 0 && opts.RateLimitDuration == 0 { - u.executerOpts.RateLimiter = ratelimit.NewUnlimited(ctx) - } else { - u.executerOpts.RateLimiter = ratelimit.New(ctx, uint(opts.RateLimit), opts.RateLimitDuration) - } + u.executerOpts.RateLimiter = utils.GetRateLimiter(ctx, opts.RateLimit, opts.RateLimitDuration) u.engine = core.New(opts) u.engine.SetExecuterOptions(u.executerOpts) return u, nil diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 9a8c669f9..471c0e73a 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -1,14 +1,17 @@ package utils import ( + "context" "errors" "fmt" "io" "net/url" "strings" + "time" "github.com/cespare/xxhash" "github.com/projectdiscovery/nuclei/v3/pkg/catalog" + "github.com/projectdiscovery/ratelimit" "github.com/projectdiscovery/retryablehttp-go" mapsutil "github.com/projectdiscovery/utils/maps" "golang.org/x/exp/constraints" @@ -71,3 +74,12 @@ func MapHash[K constraints.Ordered, V any](m map[K]V) uint64 { } return xxhash.Sum64([]byte(sb.String())) } + +// GetRateLimiter returns a rate limiter with the given max tokens and duration +// if maxTokens is 0 or duration is 0, it returns an unlimited rate limiter +func GetRateLimiter(ctx context.Context, maxTokens int, duration time.Duration) *ratelimit.Limiter { + if maxTokens == 0 || duration == 0 { + return ratelimit.NewUnlimited(ctx) + } + return ratelimit.New(ctx, uint(maxTokens), duration) +} From e1dfa1baa7a66c59190a35e503b54382fd859155 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 12 Sep 2025 18:13:23 +0200 Subject: [PATCH 122/135] adding me --- .github/auto_assign.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml index 3d6642fc5..273b6ac02 100644 --- a/.github/auto_assign.yml +++ b/.github/auto_assign.yml @@ -2,6 +2,7 @@ addReviewers: true reviewers: - dogancanbakir - dwisiswant0 + - mzack9999 numberOfReviewers: 1 skipKeywords: From fde6f7293415315e874a36e6d3696854b797d11b Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 12 Sep 2025 19:03:56 +0200 Subject: [PATCH 123/135] refactor --- pkg/external/customtemplates/github.go | 43 ++++++++++++++++++++------ 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/pkg/external/customtemplates/github.go b/pkg/external/customtemplates/github.go index 499649494..372f6479d 100644 --- a/pkg/external/customtemplates/github.go +++ b/pkg/external/customtemplates/github.go @@ -13,6 +13,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" fileutil "github.com/projectdiscovery/utils/file" folderutil "github.com/projectdiscovery/utils/folder" "golang.org/x/oauth2" @@ -46,23 +47,45 @@ func (customTemplate *customTemplateGitHubRepo) Update(ctx context.Context) { downloadPath := config.DefaultConfig.CustomGitHubTemplatesDirectory clonePath := customTemplate.getLocalRepoClonePath(downloadPath) - // If folder does not exits then clone/download the repo + // If folder does not exist then clone/download the repo if !fileutil.FolderExists(clonePath) { customTemplate.Download(ctx) return } + + // Attempt to pull changes and handle the result + customTemplate.handlePullChanges(clonePath) +} + +// handlePullChanges attempts to pull changes and logs the appropriate message +func (customTemplate *customTemplateGitHubRepo) handlePullChanges(clonePath string) { err := customTemplate.pullChanges(clonePath, customTemplate.githubToken) - if err != nil { - if errors.Is(err, git.NoErrAlreadyUpToDate) { - gologger.Info().Msgf("%s", err) - } else { - gologger.Error().Msgf("%s", err) - } - } else { - gologger.Info().Msgf("Repo %s/%s successfully pulled the changes.\n", customTemplate.owner, customTemplate.reponame) + + switch { + case err == nil: + customTemplate.logPullSuccess() + case errors.Is(err, git.NoErrAlreadyUpToDate): + customTemplate.logAlreadyUpToDate(err) + default: + customTemplate.logPullError(err) } } +// logPullSuccess logs a success message when changes are pulled +func (customTemplate *customTemplateGitHubRepo) logPullSuccess() { + gologger.Info().Msgf("Repo %s/%s successfully pulled the changes.\n", customTemplate.owner, customTemplate.reponame) +} + +// logAlreadyUpToDate logs an info message when repo is already up to date +func (customTemplate *customTemplateGitHubRepo) logAlreadyUpToDate(err error) { + gologger.Info().Msgf("%s", err) +} + +// logPullError logs an error message when pull fails +func (customTemplate *customTemplateGitHubRepo) logPullError(err error) { + gologger.Error().Msgf("%s", err) +} + // NewGitHubProviders returns new instance of GitHub providers for downloading custom templates func NewGitHubProviders(options *types.Options) ([]*customTemplateGitHubRepo, error) { providers := []*customTemplateGitHubRepo{} @@ -191,7 +214,7 @@ func (ctr *customTemplateGitHubRepo) pullChanges(repoPath, githubToken string) e err = w.Pull(pullOpts) if err != nil { - return errors.Wrapf(err, "%s/%s", ctr.owner, ctr.reponame) + return errkit.Wrapf(err, "%s/%s", ctr.owner, ctr.reponame) } return nil From ca543d7885c221a7c6ceea8990a5c30595a94635 Mon Sep 17 00:00:00 2001 From: nu11z <55335158+nu11zy@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:06:36 +0300 Subject: [PATCH 124/135] Remove the stack trace when the nuclei-ignore file does not exist (#6455) * remove the stack trace when the nuclei-ignore file does not exist * removing useless debug stack --------- Co-authored-by: Mzack9999 --- pkg/catalog/config/ignorefile.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/catalog/config/ignorefile.go b/pkg/catalog/config/ignorefile.go index 8ac7211ed..14c0ec30f 100644 --- a/pkg/catalog/config/ignorefile.go +++ b/pkg/catalog/config/ignorefile.go @@ -2,7 +2,6 @@ package config import ( "os" - "runtime/debug" "github.com/projectdiscovery/gologger" "gopkg.in/yaml.v2" @@ -18,7 +17,7 @@ type IgnoreFile struct { func ReadIgnoreFile() IgnoreFile { file, err := os.Open(DefaultConfig.GetIgnoreFilePath()) if err != nil { - gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n%s\n", err, string(debug.Stack())) + gologger.Error().Msgf("Could not read nuclei-ignore file: %s\n", err) return IgnoreFile{} } defer func() { From a65841c0344b81e490e202cff36ddccb73ecbe6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 05:08:14 +0000 Subject: [PATCH 125/135] chore(deps): bump the modules group with 7 updates Bumps the modules group with 7 updates: | Package | From | To | | --- | --- | --- | | [github.com/projectdiscovery/fastdialer](https://github.com/projectdiscovery/fastdialer) | `0.4.9` | `0.4.10` | | [github.com/projectdiscovery/hmap](https://github.com/projectdiscovery/hmap) | `0.0.93` | `0.0.94` | | [github.com/projectdiscovery/retryablehttp-go](https://github.com/projectdiscovery/retryablehttp-go) | `1.0.123` | `1.0.124` | | [github.com/projectdiscovery/dsl](https://github.com/projectdiscovery/dsl) | `0.6.0` | `0.7.0` | | [github.com/projectdiscovery/networkpolicy](https://github.com/projectdiscovery/networkpolicy) | `0.1.23` | `0.1.24` | | [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) | `0.2.45` | `0.2.46` | | [github.com/projectdiscovery/cdncheck](https://github.com/projectdiscovery/cdncheck) | `1.1.35` | `1.1.36` | Updates `github.com/projectdiscovery/fastdialer` from 0.4.9 to 0.4.10 - [Release notes](https://github.com/projectdiscovery/fastdialer/releases) - [Commits](https://github.com/projectdiscovery/fastdialer/compare/v0.4.9...v0.4.10) Updates `github.com/projectdiscovery/hmap` from 0.0.93 to 0.0.94 - [Release notes](https://github.com/projectdiscovery/hmap/releases) - [Commits](https://github.com/projectdiscovery/hmap/compare/v0.0.93...v0.0.94) Updates `github.com/projectdiscovery/retryablehttp-go` from 1.0.123 to 1.0.124 - [Release notes](https://github.com/projectdiscovery/retryablehttp-go/releases) - [Commits](https://github.com/projectdiscovery/retryablehttp-go/compare/v1.0.123...v1.0.124) Updates `github.com/projectdiscovery/dsl` from 0.6.0 to 0.7.0 - [Release notes](https://github.com/projectdiscovery/dsl/releases) - [Commits](https://github.com/projectdiscovery/dsl/compare/v0.6.0...v0.7.0) Updates `github.com/projectdiscovery/networkpolicy` from 0.1.23 to 0.1.24 - [Release notes](https://github.com/projectdiscovery/networkpolicy/releases) - [Commits](https://github.com/projectdiscovery/networkpolicy/compare/v0.1.23...v0.1.24) Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.45 to 0.2.46 - [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases) - [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.45...v0.2.46) Updates `github.com/projectdiscovery/cdncheck` from 1.1.35 to 1.1.36 - [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.35...v1.1.36) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/fastdialer dependency-version: 0.4.10 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/hmap dependency-version: 0.0.94 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/retryablehttp-go dependency-version: 1.0.124 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/dsl dependency-version: 0.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: modules - dependency-name: github.com/projectdiscovery/networkpolicy dependency-version: 0.1.24 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/wappalyzergo dependency-version: 0.2.46 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/cdncheck dependency-version: 1.1.36 dependency-type: indirect update-type: version-update:semver-patch dependency-group: modules ... Signed-off-by: dependabot[bot] --- go.mod | 17 +++++++++-------- go.sum | 30 ++++++++++++++++-------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 6d0541dab..a0a69a666 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,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.9 - github.com/projectdiscovery/hmap v0.0.93 + github.com/projectdiscovery/fastdialer v0.4.10 + github.com/projectdiscovery/hmap v0.0.94 github.com/projectdiscovery/interactsh v1.2.4 github.com/projectdiscovery/rawhttp v0.1.90 github.com/projectdiscovery/retryabledns v1.0.107 - github.com/projectdiscovery/retryablehttp-go v1.0.123 + github.com/projectdiscovery/retryablehttp-go v1.0.124 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.0 @@ -55,6 +55,7 @@ require ( github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 github.com/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697 github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883 + github.com/alexsnet/go-vnc v0.1.0 github.com/alitto/pond v1.9.2 github.com/antchfx/xmlquery v1.4.4 github.com/antchfx/xpath v1.3.3 @@ -90,7 +91,7 @@ require ( github.com/microsoft/go-mssqldb v1.9.2 github.com/ory/dockertest/v3 v3.12.0 github.com/praetorian-inc/fingerprintx v1.1.15 - github.com/projectdiscovery/dsl v0.6.0 + github.com/projectdiscovery/dsl v0.7.0 github.com/projectdiscovery/fasttemplate v0.0.2 github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb @@ -101,7 +102,7 @@ require ( github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 - github.com/projectdiscovery/networkpolicy v0.1.23 + github.com/projectdiscovery/networkpolicy v0.1.24 github.com/projectdiscovery/ratelimit v0.0.82 github.com/projectdiscovery/rdap v0.9.0 github.com/projectdiscovery/sarif v0.0.1 @@ -109,7 +110,7 @@ require ( github.com/projectdiscovery/uncover v1.1.0 github.com/projectdiscovery/useragent v0.0.101 github.com/projectdiscovery/utils v0.5.0 - github.com/projectdiscovery/wappalyzergo v0.2.45 + github.com/projectdiscovery/wappalyzergo v0.2.46 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -149,7 +150,6 @@ require ( github.com/alecthomas/kingpin/v2 v2.4.0 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/alexsnet/go-vnc v0.1.0 // indirect github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect @@ -250,6 +250,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect github.com/hdm/jarm-go v0.0.7 // indirect + github.com/iangcarroll/cookiemonster v1.6.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect @@ -317,7 +318,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.35 // indirect + github.com/projectdiscovery/cdncheck v1.1.36 // indirect 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 diff --git a/go.sum b/go.sum index 8c73280a2..aba75014a 100644 --- a/go.sum +++ b/go.sum @@ -973,6 +973,8 @@ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSo github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/iangcarroll/cookiemonster v1.6.0 h1:NPFkn/ZZYZgzXhJ1awRnYhZ3fJK3hKWgbctfTW21kew= +github.com/iangcarroll/cookiemonster v1.6.0/go.mod h1:n3MvoAq56NkNyCEyhcYs3ZJMzTc9rL3w7IaITI0apMg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -1247,14 +1249,14 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.35 h1:xyMnIWf2wzKH4Ii3lBNb73b/n9ee/baEiS3Ao23pyco= -github.com/projectdiscovery/cdncheck v1.1.35/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.1.36 h1:SIQHfBL1Kg+ydWxQV6QsMBvVLsiNdI+kQM25zGtw+Bc= +github.com/projectdiscovery/cdncheck v1.1.36/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= -github.com/projectdiscovery/dsl v0.6.0 h1:j4T6WKDx7uuhCSYjvEAySn86G7tTeEEsMeqjUauuqss= -github.com/projectdiscovery/dsl v0.6.0/go.mod h1:m+tLImvmlEnFTuwb0Bm3DqCL6e7sWOunJyxFi27AduI= -github.com/projectdiscovery/fastdialer v0.4.9 h1:/CTzoEsayQOrYJjB0CCa/0iNX7LSMeml6XmeyxX8ZVA= -github.com/projectdiscovery/fastdialer v0.4.9/go.mod h1:/4f7ELi6M5sr5XOpt+q0OpP4sQV36f3bOG23n7GOQUw= +github.com/projectdiscovery/dsl v0.7.0 h1:tfZcsVCoujXvJq2AtplMUWdSvYcQt81uDcNCfHzTLC8= +github.com/projectdiscovery/dsl v0.7.0/go.mod h1:tRkJQglLwBjaH9Z5wcf/zZOafo+G1TyrhKV6CtQnD4k= +github.com/projectdiscovery/fastdialer v0.4.10 h1:hbiB+1/xrlC3K5+dMIQgtyGB3tvnLt/QiRSFAEDb/g8= +github.com/projectdiscovery/fastdialer v0.4.10/go.mod h1:i3dKsXReeOWAkmY27+aenewBZtHZHJCyIrw1oF8aTFQ= 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= @@ -1271,8 +1273,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.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mnag8zXIAQI= github.com/projectdiscovery/gozero v0.1.0/go.mod h1:gJUNa8eQgMxLaa0UiLChPTV71/BLLrlPAaUp1C2mrhs= -github.com/projectdiscovery/hmap v0.0.93 h1:iIRdioT4byGJ4Hz5cOjo1fd3HFFi1MUFPv+EGYc1yng= -github.com/projectdiscovery/hmap v0.0.93/go.mod h1:oKgtWo2QMD7BkW25ezYbFCqKO3IctZ2ByEaG2XWW0t0= +github.com/projectdiscovery/hmap v0.0.94 h1:Q2/89U2rkDVz59j/WBzaRPmpRrYamDWnzQgauk+K03E= +github.com/projectdiscovery/hmap v0.0.94/go.mod h1:QtqZlGUwq3/SNiwEfArayfwrZU4g0/tpw6lJlxP1XEI= github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a h1:5NBp4BegAQuT3QSnbBKt05LH1nOyEeFAXYh1+aE3Nlo= github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a/go.mod h1:SQl92RiEuBnv1QQ8aQLC3b1lfgGHttoqUV0cTTvlzxQ= github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI= @@ -1285,8 +1287,8 @@ 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.23 h1:+MVm9xHCfzmZG5WhUtjAGFvNiQNKOgxZDDed1QfpLXI= -github.com/projectdiscovery/networkpolicy v0.1.23/go.mod h1:ILun9d4jgAfLOYf/NYjV+sKyW3tZTLMl+HyvaZuXZo0= +github.com/projectdiscovery/networkpolicy v0.1.24 h1:1EvBsUeKvuSVJpRR64Jf4T8852df/O7qXIFsKs/PU3o= +github.com/projectdiscovery/networkpolicy v0.1.24/go.mod h1:DEktWhDxgsQ4hrvz00XQ0GPFSFkxsD6XBOOiVUKXGuo= github.com/projectdiscovery/ratelimit v0.0.82 h1:rtO5SQf5uQFu5zTahTaTcO06OxmG8EIF1qhdFPIyTak= github.com/projectdiscovery/ratelimit v0.0.82/go.mod h1:z076BrLkBb5yS7uhHNoCTf8X/BvFSGRxwQ8EzEL9afM= github.com/projectdiscovery/rawhttp v0.1.90 h1:LOSZ6PUH08tnKmWsIwvwv1Z/4zkiYKYOSZ6n+8RFKtw= @@ -1295,8 +1297,8 @@ github.com/projectdiscovery/rdap v0.9.0 h1:wPhHx5pQ2QI+WGhyNb2PjhTl0NtB39Nk7YFZ9 github.com/projectdiscovery/rdap v0.9.0/go.mod h1:zk4yrJFQ2Hy36Aqk+DvotYQxYAeALaCJ5ORySkff36Q= github.com/projectdiscovery/retryabledns v1.0.107 h1:Rd1JK7hfL68xRg3RzXmw9Q6B6WSNv9bdPhUoGvvebyg= github.com/projectdiscovery/retryabledns v1.0.107/go.mod h1:XddeOhDpwS0qR8/T4GXRGgDQsLhtRHw3TRdMsgJs28o= -github.com/projectdiscovery/retryablehttp-go v1.0.123 h1:jnbNlYJ64ScyMIiPNpyXXX7fVpOfoII20knO2xHH+4s= -github.com/projectdiscovery/retryablehttp-go v1.0.123/go.mod h1:lv7L70Q/Lc+LARjk6ji+Ihd4Bjb9c/qmqLcdCH8Gzbo= +github.com/projectdiscovery/retryablehttp-go v1.0.124 h1:GC70rH6G+u60SolTRx1fqtI7FGHQddafWLjPOCj2Q0c= +github.com/projectdiscovery/retryablehttp-go v1.0.124/go.mod h1:wF3ct9VjSVkmd2TAzqIZzbu+e/2/qfPaw/dWyjf+aLE= 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= @@ -1309,8 +1311,8 @@ github.com/projectdiscovery/useragent v0.0.101 h1:8A+XOJ/nIH+WqW8ogLxJ/psemGp8AT github.com/projectdiscovery/useragent v0.0.101/go.mod h1:RGoRw1BQ/lJnhYMbMpEKjyAAgCaDCr/+GsULo5yEJ2I= github.com/projectdiscovery/utils v0.5.0 h1:DN7mg2DpyObLByuObXzAFEkdNRDoPUnqE5N2szd3b3c= github.com/projectdiscovery/utils v0.5.0/go.mod h1:eCAWMmyaNxyPWbiKv1oeYJLIKpxceHE2+NWx3Jodhqk= -github.com/projectdiscovery/wappalyzergo v0.2.45 h1:tx0UuYw9GjDy/FMLsL9mr3HjPXoa3qS/lFnda/zQvf4= -github.com/projectdiscovery/wappalyzergo v0.2.45/go.mod h1:1dHfTJRhrbbWBdKwl1p4QKpUDNnPYlHBBL7rEwCDdjM= +github.com/projectdiscovery/wappalyzergo v0.2.46 h1:vvHsIl8c+pM6jsbwF5zuspJrjBDEDUoEY/FqBP2SFn4= +github.com/projectdiscovery/wappalyzergo v0.2.46/go.mod h1:1dHfTJRhrbbWBdKwl1p4QKpUDNnPYlHBBL7rEwCDdjM= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= From d4f1a815ed0fc6b1a351400066ce52ff5f6994d5 Mon Sep 17 00:00:00 2001 From: Nakul Bharti Date: Mon, 15 Sep 2025 18:23:08 +0530 Subject: [PATCH 126/135] fix: update go jira deps (#6475) * fix: handle jira deprecated endpoint * refactor: update Jira issue search result structure to include 'Self' field * Revert "refactor: update Jira issue search result structure to include 'Self' field" This reverts commit b0953419d33dff3fb61f1bcdcddab0ae759379b8. * Revert "fix: handle jira deprecated endpoint" This reverts commit 1fc05076cdb31906f403d80455b2e1609a66e2ae. * chore(deps): bump github.com/andygrunwald/go-jira to v1.16.1 and tidy * fix(jira): migrate Issue.Search to SearchV2JQL with explicit Fields --- go.mod | 2 +- go.sum | 4 ++-- pkg/reporting/trackers/jira/jira.go | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index a0a69a666..a9d03e62a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.24.4 require ( github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible - github.com/andygrunwald/go-jira v1.16.0 + github.com/andygrunwald/go-jira v1.16.1 github.com/antchfx/htmlquery v1.3.4 github.com/bluele/gcache v0.0.2 github.com/go-playground/validator/v10 v10.26.0 diff --git a/go.sum b/go.sum index aba75014a..5838a14bd 100644 --- a/go.sum +++ b/go.sum @@ -387,8 +387,8 @@ github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 h1:8PmGpDEZl9 github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= -github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ= -github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU= +github.com/andygrunwald/go-jira v1.16.1 h1:WoQEar5XoDRAibOgKzTFELlPNlKAtnfWr296R9zdFLA= +github.com/andygrunwald/go-jira v1.16.1/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1jdQ= diff --git a/pkg/reporting/trackers/jira/jira.go b/pkg/reporting/trackers/jira/jira.go index 15ba85657..ebfbfd9cb 100644 --- a/pkg/reporting/trackers/jira/jira.go +++ b/pkg/reporting/trackers/jira/jira.go @@ -437,11 +437,12 @@ func (i *Integration) FindExistingIssue(event *output.ResultEvent, useStatus boo jql = fmt.Sprintf("%s AND status != \"%s\"", jql, i.options.StatusNot) } - searchOptions := &jira.SearchOptions{ + searchOptions := &jira.SearchOptionsV2{ MaxResults: 1, // if any issue exists, then we won't create a new one + Fields: []string{"summary", "description", "issuetype", "status", "priority", "project"}, } - chunk, resp, err := i.jira.Issue.Search(jql, searchOptions) + issues, resp, err := i.jira.Issue.SearchV2JQL(jql, searchOptions) if err != nil { var data string if resp != nil && resp.Body != nil { @@ -455,10 +456,10 @@ func (i *Integration) FindExistingIssue(event *output.ResultEvent, useStatus boo case 0: return jira.Issue{}, nil case 1: - return chunk[0], nil + return issues[0], nil default: - gologger.Warning().Msgf("Discovered multiple opened issues %s for the host %s: The issue [%s] will be updated.", template, event.Host, chunk[0].ID) - return chunk[0], nil + gologger.Warning().Msgf("Discovered multiple opened issues %s for the host %s: The issue [%s] will be updated.", template, event.Host, issues[0].ID) + return issues[0], nil } } From c4fa2c74c1e5831a510d9ae8230ac439b7ebbb05 Mon Sep 17 00:00:00 2001 From: Nakul Bharti Date: Mon, 15 Sep 2025 23:48:02 +0530 Subject: [PATCH 127/135] cache, goroutine and unbounded workers management (#6420) * Enhance matcher compilation with caching for regex and DSL expressions to improve performance. Update template parsing to conditionally retain raw templates based on size constraints. * Implement caching for regex and DSL expressions in extractors and matchers to enhance performance. Introduce a buffer pool in raw requests to reduce memory allocations. Update template cache management for improved efficiency. * feat: improve concurrency to be bound * refactor: replace fmt.Sprintf with fmt.Fprintf for improved performance in header handling * feat: add regex matching tests and benchmarks for performance evaluation * feat: add prefix check in regex extraction to optimize matching process * feat: implement regex caching mechanism to enhance performance in extractors and matchers, along with tests and benchmarks for validation * feat: add unit tests for template execution in the core engine, enhancing test coverage and reliability * feat: enhance error handling in template execution and improve regex caching logic for better performance * Implement caching for regex and DSL expressions in the cache package, replacing previous sync.Map usage. Add unit tests for cache functionality, including eviction by capacity and retrieval of cached items. Update extractors and matchers to utilize the new cache system for improved performance and memory efficiency. * Add tests for SetCapacities in cache package to ensure cache behavior on capacity changes - Implemented TestSetCapacities_NoRebuildOnZero to verify that setting capacities to zero does not clear existing caches. - Added TestSetCapacities_BeforeFirstUse to confirm that initial cache settings are respected and not overridden by subsequent capacity changes. * Refactor matchers and update load test generator to use io package - Removed maxRegexScanBytes constant from match.go. - Replaced ioutil with io package in load_test.go for NopCloser usage. - Restored TestValidate_AllowsInlineMultiline in load_test.go to ensure inline validation functionality. * Add cancellation support in template execution and enhance test coverage - Updated executeTemplateWithTargets to respect context cancellation. - Introduced fakeTargetProvider and slowExecuter for testing. - Added Test_executeTemplateWithTargets_RespectsCancellation to validate cancellation behavior during template execution. --- pkg/core/executors.go | 129 +++++++----- pkg/core/executors_test.go | 148 +++++++++++++ pkg/operators/cache/cache.go | 62 ++++++ pkg/operators/cache/cache_test.go | 114 ++++++++++ pkg/operators/extractors/compile.go | 11 + pkg/operators/extractors/extract.go | 14 +- pkg/operators/matchers/compile.go | 16 +- pkg/operators/matchers/match.go | 38 +++- pkg/operators/matchers/match_test.go | 65 +++++- .../common/generators/attack_types_test.go | 26 +++ pkg/protocols/common/generators/env_test.go | 38 ++++ pkg/protocols/common/generators/load.go | 14 ++ pkg/protocols/common/generators/load_test.go | 198 ++++++++---------- pkg/protocols/common/generators/maps_test.go | 29 +++ pkg/protocols/common/generators/validate.go | 6 +- pkg/protocols/http/build_request.go | 5 +- pkg/protocols/http/raw/raw.go | 19 +- pkg/protocols/http/raw/raw_test.go | 15 ++ pkg/protocols/http/request.go | 81 +++++-- pkg/protocols/http/request_test.go | 114 ++++++++++ pkg/protocols/javascript/js.go | 5 +- pkg/reporting/reporting.go | 10 +- pkg/templates/cache.go | 30 ++- pkg/templates/templates.go | 8 +- pkg/templates/templates_test.go | 26 +++ 25 files changed, 1001 insertions(+), 220 deletions(-) create mode 100644 pkg/core/executors_test.go create mode 100644 pkg/operators/cache/cache.go create mode 100644 pkg/operators/cache/cache_test.go create mode 100644 pkg/protocols/common/generators/attack_types_test.go create mode 100644 pkg/protocols/common/generators/env_test.go diff --git a/pkg/core/executors.go b/pkg/core/executors.go index 8abcc9d78..aeb85ddfe 100644 --- a/pkg/core/executors.go +++ b/pkg/core/executors.go @@ -48,8 +48,15 @@ func (e *Engine) executeAllSelfContained(ctx context.Context, alltemplates []*te // executeTemplateWithTargets executes a given template on x targets (with a internal targetpool(i.e concurrency)) func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templates.Template, target provider.InputProvider, results *atomic.Bool) { - // this is target pool i.e max target to execute - wg := e.workPool.InputPool(template.Type()) + if e.workPool == nil { + e.workPool = e.GetWorkPool() + } + // Bounded worker pool using input concurrency + pool := e.workPool.InputPool(template.Type()) + workerCount := 1 + if pool != nil && pool.Size > 0 { + workerCount = pool.Size + } var ( index uint32 @@ -78,6 +85,41 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ currentInfo.Unlock() } + // task represents a single target execution unit + type task struct { + index uint32 + skip bool + value *contextargs.MetaInput + } + + tasks := make(chan task) + var workersWg sync.WaitGroup + workersWg.Add(workerCount) + for i := 0; i < workerCount; i++ { + go func() { + defer workersWg.Done() + for t := range tasks { + func() { + defer cleanupInFlight(t.index) + select { + case <-ctx.Done(): + return + default: + } + if t.skip { + return + } + + match, err := e.executeTemplateOnInput(ctx, template, t.value) + if err != nil { + e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), t.value.Input, err) + } + results.CompareAndSwap(false, match) + }() + } + }() + } + target.Iterate(func(scannedValue *contextargs.MetaInput) bool { select { case <-ctx.Done(): @@ -128,43 +170,13 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ return true } - wg.Add() - go func(index uint32, skip bool, value *contextargs.MetaInput) { - defer wg.Done() - defer cleanupInFlight(index) - if skip { - return - } - - var match bool - var err error - ctxArgs := contextargs.New(ctx) - ctxArgs.MetaInput = value - ctx := scan.NewScanContext(ctx, ctxArgs) - switch template.Type() { - case types.WorkflowProtocol: - match = e.executeWorkflow(ctx, template.CompiledWorkflow) - default: - if e.Callback != nil { - if results, err := template.Executer.ExecuteWithResults(ctx); err == nil { - for _, result := range results { - e.Callback(result) - } - } - match = true - } else { - match, err = template.Executer.Execute(ctx) - } - } - if err != nil { - e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) - } - results.CompareAndSwap(false, match) - }(index, skip, scannedValue) + tasks <- task{index: index, skip: skip, value: scannedValue} index++ return true }) - wg.Wait() + + close(tasks) + workersWg.Wait() // on completion marks the template as completed currentInfo.Lock() @@ -202,26 +214,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t go func(template *templates.Template, value *contextargs.MetaInput, wg *syncutil.AdaptiveWaitGroup) { defer wg.Done() - var match bool - var err error - ctxArgs := contextargs.New(ctx) - ctxArgs.MetaInput = value - ctx := scan.NewScanContext(ctx, ctxArgs) - switch template.Type() { - case types.WorkflowProtocol: - match = e.executeWorkflow(ctx, template.CompiledWorkflow) - default: - if e.Callback != nil { - if results, err := template.Executer.ExecuteWithResults(ctx); err == nil { - for _, result := range results { - e.Callback(result) - } - } - match = true - } else { - match, err = template.Executer.Execute(ctx) - } - } + match, err := e.executeTemplateOnInput(ctx, template, value) if err != nil { e.options.Logger.Warning().Msgf("[%s] Could not execute step on %s: %s\n", e.executerOpts.Colorizer.BrightBlue(template.ID), value.Input, err) } @@ -229,3 +222,27 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t }(tpl, target, sg) } } + +// executeTemplateOnInput performs template execution for a single input and returns match status and error +func (e *Engine) executeTemplateOnInput(ctx context.Context, template *templates.Template, value *contextargs.MetaInput) (bool, error) { + ctxArgs := contextargs.New(ctx) + ctxArgs.MetaInput = value + scanCtx := scan.NewScanContext(ctx, ctxArgs) + + switch template.Type() { + case types.WorkflowProtocol: + return e.executeWorkflow(scanCtx, template.CompiledWorkflow), nil + default: + if e.Callback != nil { + results, err := template.Executer.ExecuteWithResults(scanCtx) + if err != nil { + return false, err + } + for _, result := range results { + e.Callback(result) + } + return len(results) > 0, nil + } + return template.Executer.Execute(scanCtx) + } +} diff --git a/pkg/core/executors_test.go b/pkg/core/executors_test.go new file mode 100644 index 000000000..394b2e6d9 --- /dev/null +++ b/pkg/core/executors_test.go @@ -0,0 +1,148 @@ +package core + +import ( + "context" + "fmt" + "sync/atomic" + "testing" + "time" + + inputtypes "github.com/projectdiscovery/nuclei/v3/pkg/input/types" + "github.com/projectdiscovery/nuclei/v3/pkg/output" + "github.com/projectdiscovery/nuclei/v3/pkg/protocols" + "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs" + "github.com/projectdiscovery/nuclei/v3/pkg/scan" + "github.com/projectdiscovery/nuclei/v3/pkg/templates" + tmpltypes "github.com/projectdiscovery/nuclei/v3/pkg/templates/types" + "github.com/projectdiscovery/nuclei/v3/pkg/types" +) + +// fakeExecuter is a simple stub for protocols.Executer used to test executeTemplateOnInput +type fakeExecuter struct { + withResults bool +} + +func (f *fakeExecuter) Compile() error { return nil } +func (f *fakeExecuter) Requests() int { return 1 } +func (f *fakeExecuter) Execute(ctx *scan.ScanContext) (bool, error) { return !f.withResults, nil } +func (f *fakeExecuter) ExecuteWithResults(ctx *scan.ScanContext) ([]*output.ResultEvent, error) { + if !f.withResults { + return nil, nil + } + return []*output.ResultEvent{{Host: "h"}}, nil +} + +// newTestEngine creates a minimal Engine for tests +func newTestEngine() *Engine { + return New(&types.Options{}) +} + +func Test_executeTemplateOnInput_CallbackPath(t *testing.T) { + e := newTestEngine() + called := 0 + e.Callback = func(*output.ResultEvent) { called++ } + + tpl := &templates.Template{} + tpl.Executer = &fakeExecuter{withResults: true} + + ok, err := e.executeTemplateOnInput(context.Background(), tpl, &contextargs.MetaInput{Input: "x"}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !ok { + t.Fatalf("expected match true") + } + if called == 0 { + t.Fatalf("expected callback to be called") + } +} + +func Test_executeTemplateOnInput_ExecutePath(t *testing.T) { + e := newTestEngine() + tpl := &templates.Template{} + tpl.Executer = &fakeExecuter{withResults: false} + + ok, err := e.executeTemplateOnInput(context.Background(), tpl, &contextargs.MetaInput{Input: "x"}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !ok { + t.Fatalf("expected match true from Execute path") + } +} + +type fakeExecuterErr struct{} + +func (f *fakeExecuterErr) Compile() error { return nil } +func (f *fakeExecuterErr) Requests() int { return 1 } +func (f *fakeExecuterErr) Execute(ctx *scan.ScanContext) (bool, error) { return false, nil } +func (f *fakeExecuterErr) ExecuteWithResults(ctx *scan.ScanContext) ([]*output.ResultEvent, error) { + return nil, fmt.Errorf("boom") +} + +func Test_executeTemplateOnInput_CallbackErrorPropagates(t *testing.T) { + e := newTestEngine() + e.Callback = func(*output.ResultEvent) {} + tpl := &templates.Template{} + tpl.Executer = &fakeExecuterErr{} + + ok, err := e.executeTemplateOnInput(context.Background(), tpl, &contextargs.MetaInput{Input: "x"}) + if err == nil { + t.Fatalf("expected error to propagate") + } + if ok { + t.Fatalf("expected match to be false on error") + } +} + +type fakeTargetProvider struct { + values []*contextargs.MetaInput +} + +func (f *fakeTargetProvider) Count() int64 { return int64(len(f.values)) } +func (f *fakeTargetProvider) Iterate(cb func(value *contextargs.MetaInput) bool) { + for _, v := range f.values { + if !cb(v) { + return + } + } +} +func (f *fakeTargetProvider) Set(string, string) {} +func (f *fakeTargetProvider) SetWithProbe(string, string, inputtypes.InputLivenessProbe) error { + return nil +} +func (f *fakeTargetProvider) SetWithExclusions(string, string) error { return nil } +func (f *fakeTargetProvider) InputType() string { return "test" } +func (f *fakeTargetProvider) Close() {} + +type slowExecuter struct{} + +func (s *slowExecuter) Compile() error { return nil } +func (s *slowExecuter) Requests() int { return 1 } +func (s *slowExecuter) Execute(ctx *scan.ScanContext) (bool, error) { + select { + case <-ctx.Context().Done(): + return false, ctx.Context().Err() + case <-time.After(200 * time.Millisecond): + return true, nil + } +} +func (s *slowExecuter) ExecuteWithResults(ctx *scan.ScanContext) ([]*output.ResultEvent, error) { + return nil, nil +} + +func Test_executeTemplateWithTargets_RespectsCancellation(t *testing.T) { + e := newTestEngine() + e.SetExecuterOptions(&protocols.ExecutorOptions{Logger: e.Logger, ResumeCfg: types.NewResumeCfg(), ProtocolType: tmpltypes.HTTPProtocol}) + + tpl := &templates.Template{} + tpl.Executer = &slowExecuter{} + + targets := &fakeTargetProvider{values: []*contextargs.MetaInput{{Input: "a"}, {Input: "b"}, {Input: "c"}}} + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + var matched atomic.Bool + e.executeTemplateWithTargets(ctx, tpl, targets, &matched) +} diff --git a/pkg/operators/cache/cache.go b/pkg/operators/cache/cache.go new file mode 100644 index 000000000..ca486097c --- /dev/null +++ b/pkg/operators/cache/cache.go @@ -0,0 +1,62 @@ +package cache + +import ( + "regexp" + "sync" + + "github.com/Knetic/govaluate" + "github.com/projectdiscovery/gcache" +) + +var ( + initOnce sync.Once + mu sync.RWMutex + + regexCap = 4096 + dslCap = 4096 + + regexCache gcache.Cache[string, *regexp.Regexp] + dslCache gcache.Cache[string, *govaluate.EvaluableExpression] +) + +func initCaches() { + initOnce.Do(func() { + regexCache = gcache.New[string, *regexp.Regexp](regexCap).LRU().Build() + dslCache = gcache.New[string, *govaluate.EvaluableExpression](dslCap).LRU().Build() + }) +} + +func SetCapacities(regexCapacity, dslCapacity int) { + // ensure caches are initialized under initOnce, so later Regex()/DSL() won't re-init + initCaches() + + mu.Lock() + defer mu.Unlock() + + if regexCapacity > 0 { + regexCap = regexCapacity + } + if dslCapacity > 0 { + dslCap = dslCapacity + } + if regexCapacity <= 0 && dslCapacity <= 0 { + return + } + // rebuild caches with new capacities + regexCache = gcache.New[string, *regexp.Regexp](regexCap).LRU().Build() + dslCache = gcache.New[string, *govaluate.EvaluableExpression](dslCap).LRU().Build() +} + +func Regex() gcache.Cache[string, *regexp.Regexp] { + initCaches() + mu.RLock() + defer mu.RUnlock() + return regexCache +} + +func DSL() gcache.Cache[string, *govaluate.EvaluableExpression] { + initCaches() + mu.RLock() + defer mu.RUnlock() + return dslCache +} diff --git a/pkg/operators/cache/cache_test.go b/pkg/operators/cache/cache_test.go new file mode 100644 index 000000000..c44b72c84 --- /dev/null +++ b/pkg/operators/cache/cache_test.go @@ -0,0 +1,114 @@ +package cache + +import ( + "regexp" + "testing" + + "github.com/Knetic/govaluate" +) + +func TestRegexCache_SetGet(t *testing.T) { + // ensure init + c := Regex() + pattern := "abc(\n)?123" + re, err := regexp.Compile(pattern) + if err != nil { + t.Fatalf("compile: %v", err) + } + if err := c.Set(pattern, re); err != nil { + t.Fatalf("set: %v", err) + } + got, err := c.GetIFPresent(pattern) + if err != nil || got == nil { + t.Fatalf("get: %v got=%v", err, got) + } + if got.String() != re.String() { + t.Fatalf("mismatch: %s != %s", got.String(), re.String()) + } +} + +func TestDSLCache_SetGet(t *testing.T) { + c := DSL() + expr := "1 + 2 == 3" + ast, err := govaluate.NewEvaluableExpression(expr) + if err != nil { + t.Fatalf("dsl compile: %v", err) + } + if err := c.Set(expr, ast); err != nil { + t.Fatalf("set: %v", err) + } + got, err := c.GetIFPresent(expr) + if err != nil || got == nil { + t.Fatalf("get: %v got=%v", err, got) + } + if got.String() != ast.String() { + t.Fatalf("mismatch: %s != %s", got.String(), ast.String()) + } +} + +func TestRegexCache_EvictionByCapacity(t *testing.T) { + SetCapacities(3, 3) + c := Regex() + for i := 0; i < 5; i++ { + k := string(rune('a' + i)) + re := regexp.MustCompile(k) + _ = c.Set(k, re) + } + // last 3 keys expected to remain under LRU: 'c','d','e' + if _, err := c.GetIFPresent("a"); err == nil { + t.Fatalf("expected 'a' to be evicted") + } + if _, err := c.GetIFPresent("b"); err == nil { + t.Fatalf("expected 'b' to be evicted") + } + if _, err := c.GetIFPresent("c"); err != nil { + t.Fatalf("expected 'c' present") + } +} + +func TestSetCapacities_NoRebuildOnZero(t *testing.T) { + // init + SetCapacities(4, 4) + c1 := Regex() + _ = c1.Set("k", regexp.MustCompile("k")) + if _, err := c1.GetIFPresent("k"); err != nil { + t.Fatalf("expected key present: %v", err) + } + // zero changes should not rebuild/clear caches + SetCapacities(0, 0) + c2 := Regex() + if _, err := c2.GetIFPresent("k"); err != nil { + t.Fatalf("key lost after zero-capacity SetCapacities: %v", err) + } +} + +func TestSetCapacities_BeforeFirstUse(t *testing.T) { + // This should not be overridden by later initCaches + SetCapacities(2, 0) + c := Regex() + _ = c.Set("a", regexp.MustCompile("a")) + _ = c.Set("b", regexp.MustCompile("b")) + _ = c.Set("c", regexp.MustCompile("c")) + if _, err := c.GetIFPresent("a"); err == nil { + t.Fatalf("expected 'a' to be evicted under cap=2") + } +} + +func TestSetCapacities_ConcurrentAccess(t *testing.T) { + SetCapacities(64, 64) + stop := make(chan struct{}) + + go func() { + for i := 0; i < 5000; i++ { + _ = Regex().Set("k"+string(rune('a'+(i%26))), regexp.MustCompile("a")) + _, _ = Regex().GetIFPresent("k" + string(rune('a'+(i%26)))) + _, _ = DSL().GetIFPresent("1+2==3") + } + close(stop) + }() + + for i := 0; i < 200; i++ { + SetCapacities(64+(i%5), 64+((i+1)%5)) + } + <-stop +} diff --git a/pkg/operators/extractors/compile.go b/pkg/operators/extractors/compile.go index 2b55d374a..bcfd37eeb 100644 --- a/pkg/operators/extractors/compile.go +++ b/pkg/operators/extractors/compile.go @@ -7,6 +7,7 @@ import ( "github.com/Knetic/govaluate" "github.com/itchyny/gojq" + "github.com/projectdiscovery/nuclei/v3/pkg/operators/cache" "github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl" ) @@ -20,10 +21,15 @@ func (e *Extractor) CompileExtractors() error { e.extractorType = computedType // Compile the regexes for _, regex := range e.Regex { + if cached, err := cache.Regex().GetIFPresent(regex); err == nil && cached != nil { + e.regexCompiled = append(e.regexCompiled, cached) + continue + } compiled, err := regexp.Compile(regex) if err != nil { return fmt.Errorf("could not compile regex: %s", regex) } + _ = cache.Regex().Set(regex, compiled) e.regexCompiled = append(e.regexCompiled, compiled) } for i, kval := range e.KVal { @@ -43,10 +49,15 @@ func (e *Extractor) CompileExtractors() error { } for _, dslExp := range e.DSL { + if cached, err := cache.DSL().GetIFPresent(dslExp); err == nil && cached != nil { + e.dslCompiled = append(e.dslCompiled, cached) + continue + } compiled, err := govaluate.NewEvaluableExpressionWithFunctions(dslExp, dsl.HelperFunctions) if err != nil { return &dsl.CompilationError{DslSignature: dslExp, WrappedError: err} } + _ = cache.DSL().Set(dslExp, compiled) e.dslCompiled = append(e.dslCompiled, compiled) } diff --git a/pkg/operators/extractors/extract.go b/pkg/operators/extractors/extract.go index 194b4648f..1a8ca63b6 100644 --- a/pkg/operators/extractors/extract.go +++ b/pkg/operators/extractors/extract.go @@ -17,9 +17,19 @@ func (e *Extractor) ExtractRegex(corpus string) map[string]struct{} { groupPlusOne := e.RegexGroup + 1 for _, regex := range e.regexCompiled { - matches := regex.FindAllStringSubmatch(corpus, -1) + // skip prefix short-circuit for case-insensitive patterns + rstr := regex.String() + if !strings.Contains(rstr, "(?i") { + if prefix, ok := regex.LiteralPrefix(); ok && prefix != "" { + if !strings.Contains(corpus, prefix) { + continue + } + } + } - for _, match := range matches { + submatches := regex.FindAllStringSubmatch(corpus, -1) + + for _, match := range submatches { if len(match) < groupPlusOne { continue } diff --git a/pkg/operators/matchers/compile.go b/pkg/operators/matchers/compile.go index 5a99347c5..4ae72be60 100644 --- a/pkg/operators/matchers/compile.go +++ b/pkg/operators/matchers/compile.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/Knetic/govaluate" - + "github.com/projectdiscovery/nuclei/v3/pkg/operators/cache" "github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl" ) @@ -42,12 +42,17 @@ func (matcher *Matcher) CompileMatchers() error { matcher.Part = "body" } - // Compile the regexes + // Compile the regexes (with shared cache) for _, regex := range matcher.Regex { + if cached, err := cache.Regex().GetIFPresent(regex); err == nil && cached != nil { + matcher.regexCompiled = append(matcher.regexCompiled, cached) + continue + } compiled, err := regexp.Compile(regex) if err != nil { return fmt.Errorf("could not compile regex: %s", regex) } + _ = cache.Regex().Set(regex, compiled) matcher.regexCompiled = append(matcher.regexCompiled, compiled) } @@ -60,12 +65,17 @@ func (matcher *Matcher) CompileMatchers() error { } } - // Compile the dsl expressions + // Compile the dsl expressions (with shared cache) for _, dslExpression := range matcher.DSL { + if cached, err := cache.DSL().GetIFPresent(dslExpression); err == nil && cached != nil { + matcher.dslCompiled = append(matcher.dslCompiled, cached) + continue + } compiledExpression, err := govaluate.NewEvaluableExpressionWithFunctions(dslExpression, dsl.HelperFunctions) if err != nil { return &dsl.CompilationError{DslSignature: dslExpression, WrappedError: err} } + _ = cache.DSL().Set(dslExpression, compiledExpression) matcher.dslCompiled = append(matcher.dslCompiled, compiledExpression) } diff --git a/pkg/operators/matchers/match.go b/pkg/operators/matchers/match.go index 78bd40175..a914b5f98 100644 --- a/pkg/operators/matchers/match.go +++ b/pkg/operators/matchers/match.go @@ -106,10 +106,33 @@ func (matcher *Matcher) MatchRegex(corpus string) (bool, []string) { var matchedRegexes []string // Iterate over all the regexes accepted as valid for i, regex := range matcher.regexCompiled { - // Continue if the regex doesn't match - if !regex.MatchString(corpus) { - // If we are in an AND request and a match failed, - // return false as the AND condition fails on any single mismatch. + // Literal prefix short-circuit + rstr := regex.String() + if !strings.Contains(rstr, "(?i") { // covers (?i) and (?i: + if prefix, ok := regex.LiteralPrefix(); ok && prefix != "" { + if !strings.Contains(corpus, prefix) { + switch matcher.condition { + case ANDCondition: + return false, []string{} + case ORCondition: + continue + } + } + } + } + + // Fast OR-path: return first match without full scan + if matcher.condition == ORCondition && !matcher.MatchAll { + m := regex.FindAllString(corpus, 1) + if len(m) == 0 { + continue + } + return true, m + } + + // Single scan: get all matches directly + currentMatches := regex.FindAllString(corpus, -1) + if len(currentMatches) == 0 { switch matcher.condition { case ANDCondition: return false, []string{} @@ -118,12 +141,7 @@ func (matcher *Matcher) MatchRegex(corpus string) (bool, []string) { } } - currentMatches := regex.FindAllString(corpus, -1) - // If the condition was an OR, return on the first match. - if matcher.condition == ORCondition && !matcher.MatchAll { - return true, currentMatches - } - + // If the condition was an OR (and MatchAll true), we still need to gather all matchedRegexes = append(matchedRegexes, currentMatches...) // If we are at the end of the regex, return with true diff --git a/pkg/operators/matchers/match_test.go b/pkg/operators/matchers/match_test.go index ea6258ae0..8a073318b 100644 --- a/pkg/operators/matchers/match_test.go +++ b/pkg/operators/matchers/match_test.go @@ -84,7 +84,7 @@ func TestMatcher_MatchDSL(t *testing.T) { values := []string{"PING", "pong"} - for value := range values { + for _, value := range values { isMatched := m.MatchDSL(map[string]interface{}{"body": value, "VARIABLE": value}) require.True(t, isMatched) } @@ -209,3 +209,66 @@ func TestMatcher_MatchXPath_XML(t *testing.T) { isMatched = m.MatchXPath("

not right notvalid") require.False(t, isMatched, "Invalid xpath did not return false") } + +func TestMatchRegex_CaseInsensitivePrefixSkip(t *testing.T) { + m := &Matcher{Type: MatcherTypeHolder{MatcherType: RegexMatcher}, Condition: "or", Regex: []string{"(?i)abc"}} + err := m.CompileMatchers() + require.NoError(t, err) + ok, got := m.MatchRegex("zzz AbC yyy") + require.True(t, ok) + require.NotEmpty(t, got) +} + +func TestMatchStatusCodeAndSize(t *testing.T) { + mStatus := &Matcher{Status: []int{200, 302}} + require.True(t, mStatus.MatchStatusCode(200)) + require.True(t, mStatus.MatchStatusCode(302)) + require.False(t, mStatus.MatchStatusCode(404)) + + mSize := &Matcher{Size: []int{5, 10}} + require.True(t, mSize.MatchSize(5)) + require.False(t, mSize.MatchSize(7)) +} + +func TestMatchBinary_AND_OR(t *testing.T) { + // AND should fail if any binary not present + mAnd := &Matcher{Type: MatcherTypeHolder{MatcherType: BinaryMatcher}, Condition: "and", Binary: []string{"50494e47", "414141"}} // "PING", "AAA" + require.NoError(t, mAnd.CompileMatchers()) + ok, _ := mAnd.MatchBinary("PING") + require.False(t, ok) + // OR should succeed if any present + mOr := &Matcher{Type: MatcherTypeHolder{MatcherType: BinaryMatcher}, Condition: "or", Binary: []string{"414141", "50494e47"}} // "AAA", "PING" + require.NoError(t, mOr.CompileMatchers()) + ok, got := mOr.MatchBinary("xxPINGyy") + require.True(t, ok) + require.NotEmpty(t, got) +} + +func TestMatchRegex_LiteralPrefixShortCircuit(t *testing.T) { + // AND: first regex has literal prefix "abc"; corpus lacks it => early false + mAnd := &Matcher{Type: MatcherTypeHolder{MatcherType: RegexMatcher}, Condition: "and", Regex: []string{"abc[0-9]*", "[0-9]{2}"}} + require.NoError(t, mAnd.CompileMatchers()) + ok, matches := mAnd.MatchRegex("zzz 12 yyy") + require.False(t, ok) + require.Empty(t, matches) + + // OR: first regex skipped due to missing prefix, second matches => true + mOr := &Matcher{Type: MatcherTypeHolder{MatcherType: RegexMatcher}, Condition: "or", Regex: []string{"abc[0-9]*", "[0-9]{2}"}} + require.NoError(t, mOr.CompileMatchers()) + ok, matches = mOr.MatchRegex("zzz 12 yyy") + require.True(t, ok) + require.Equal(t, []string{"12"}, matches) +} + +func TestMatcher_MatchDSL_ErrorHandling(t *testing.T) { + // First expression errors (division by zero), second is true + bad, err := govaluate.NewEvaluableExpression("1 / 0") + require.NoError(t, err) + good, err := govaluate.NewEvaluableExpression("1 == 1") + require.NoError(t, err) + + m := &Matcher{Type: MatcherTypeHolder{MatcherType: DSLMatcher}, Condition: "or", dslCompiled: []*govaluate.EvaluableExpression{bad, good}} + require.NoError(t, m.CompileMatchers()) + ok := m.MatchDSL(map[string]interface{}{}) + require.True(t, ok) +} diff --git a/pkg/protocols/common/generators/attack_types_test.go b/pkg/protocols/common/generators/attack_types_test.go new file mode 100644 index 000000000..a1c808319 --- /dev/null +++ b/pkg/protocols/common/generators/attack_types_test.go @@ -0,0 +1,26 @@ +package generators + +import "testing" + +func TestAttackTypeHelpers(t *testing.T) { + // GetSupportedAttackTypes should include three values + types := GetSupportedAttackTypes() + if len(types) != 3 { + t.Fatalf("expected 3 types, got %d", len(types)) + } + // toAttackType valid + if got, err := toAttackType("pitchfork"); err != nil || got != PitchForkAttack { + t.Fatalf("toAttackType failed: %v %v", got, err) + } + // toAttackType invalid + if _, err := toAttackType("nope"); err == nil { + t.Fatalf("expected error for invalid attack type") + } + // normalizeValue and String + if normalizeValue(" ClusterBomb ") != "clusterbomb" { + t.Fatalf("normalizeValue failed") + } + if ClusterBombAttack.String() != "clusterbomb" { + t.Fatalf("String failed") + } +} diff --git a/pkg/protocols/common/generators/env_test.go b/pkg/protocols/common/generators/env_test.go new file mode 100644 index 000000000..88b8fa377 --- /dev/null +++ b/pkg/protocols/common/generators/env_test.go @@ -0,0 +1,38 @@ +package generators + +import ( + "os" + "testing" +) + +func TestParseEnvVars(t *testing.T) { + old := os.Environ() + // set a scoped env var + _ = os.Setenv("NUCLEI_TEST_K", "V1") + t.Cleanup(func() { + // restore + for _, kv := range old { + parts := kv + _ = parts // nothing, environment already has superset; best-effort cleanup below + } + _ = os.Unsetenv("NUCLEI_TEST_K") + }) + vars := parseEnvVars() + if vars["NUCLEI_TEST_K"] != "V1" { + t.Fatalf("expected V1, got %v", vars["NUCLEI_TEST_K"]) + } +} + +func TestEnvVarsMemoization(t *testing.T) { + // reset memoized map + envVars = nil + _ = os.Setenv("NUCLEI_TEST_MEMO", "A") + t.Cleanup(func() { _ = os.Unsetenv("NUCLEI_TEST_MEMO") }) + v1 := EnvVars()["NUCLEI_TEST_MEMO"] + // change env after memoization + _ = os.Setenv("NUCLEI_TEST_MEMO", "B") + v2 := EnvVars()["NUCLEI_TEST_MEMO"] + if v1 != "A" || v2 != "A" { + t.Fatalf("memoization failed: %v %v", v1, v2) + } +} diff --git a/pkg/protocols/common/generators/load.go b/pkg/protocols/common/generators/load.go index 892fe358a..91f631e4b 100644 --- a/pkg/protocols/common/generators/load.go +++ b/pkg/protocols/common/generators/load.go @@ -17,6 +17,20 @@ func (generator *PayloadGenerator) loadPayloads(payloads map[string]interface{}, for name, payload := range payloads { switch pt := payload.(type) { case string: + // Fast path: if no newline, treat as file path + if !strings.ContainsRune(pt, '\n') { + file, err := generator.options.LoadHelperFile(pt, templatePath, generator.catalog) + if err != nil { + return nil, errors.Wrap(err, "could not load payload file") + } + payloads, err := generator.loadPayloadsFromFile(file) + if err != nil { + return nil, errors.Wrap(err, "could not load payloads") + } + loadedPayloads[name] = payloads + break + } + // Multiline inline payloads elements := strings.Split(pt, "\n") //golint:gomnd // this is not a magic number if len(elements) >= 2 { diff --git a/pkg/protocols/common/generators/load_test.go b/pkg/protocols/common/generators/load_test.go index ebec9fd72..04d886270 100644 --- a/pkg/protocols/common/generators/load_test.go +++ b/pkg/protocols/common/generators/load_test.go @@ -1,120 +1,108 @@ package generators import ( - "os" - "os/exec" - "path/filepath" + "io" + "strings" "testing" - "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config" - "github.com/projectdiscovery/nuclei/v3/pkg/catalog/disk" - osutils "github.com/projectdiscovery/utils/os" - "github.com/stretchr/testify/require" + "github.com/pkg/errors" + "github.com/projectdiscovery/nuclei/v3/pkg/catalog" + "github.com/projectdiscovery/nuclei/v3/pkg/types" ) -func TestLoadPayloads(t *testing.T) { - // since we are changing value of global variable i.e templates directory - // run this test as subprocess - if os.Getenv("LOAD_PAYLOAD_NO_ACCESS") != "1" { - cmd := exec.Command(os.Args[0], "-test.run=TestLoadPayloadsWithAccess") - cmd.Env = append(os.Environ(), "LOAD_PAYLOAD_NO_ACCESS=1") - err := cmd.Run() - if e, ok := err.(*exec.ExitError); ok && !e.Success() { - return - } - if err != nil { - t.Fatalf("process ran with err %v, want exit status 1", err) +type fakeCatalog struct{ catalog.Catalog } + +func (f *fakeCatalog) OpenFile(filename string) (io.ReadCloser, error) { + return nil, errors.New("not used") +} +func (f *fakeCatalog) GetTemplatePath(target string) ([]string, error) { return nil, nil } +func (f *fakeCatalog) GetTemplatesPath(definitions []string) ([]string, map[string]error) { + return nil, nil +} +func (f *fakeCatalog) ResolvePath(templateName, second string) (string, error) { + return templateName, nil +} + +func newTestGenerator() *PayloadGenerator { + opts := types.DefaultOptions() + // inject helper loader function + opts.LoadHelperFileFunction = func(path, templatePath string, _ catalog.Catalog) (io.ReadCloser, error) { + switch path { + case "fileA.txt": + return io.NopCloser(strings.NewReader("one\n two\n\nthree\n")), nil + default: + return io.NopCloser(strings.NewReader("x\ny\nz\n")), nil } } - templateDir := getTemplatesDir(t) - config.DefaultConfig.SetTemplatesDir(templateDir) - - generator := &PayloadGenerator{catalog: disk.NewCatalog(templateDir), options: getOptions(false)} - fullpath := filepath.Join(templateDir, "payloads.txt") - - // Test sandbox - t.Run("templates-directory", func(t *testing.T) { - // testcase when loading file from template directory and template file is in root - // expected to succeed - values, err := generator.loadPayloads(map[string]interface{}{ - "new": fullpath, - }, "/test") - require.NoError(t, err, "could not load payloads") - require.Equal(t, map[string][]string{"new": {"test", "another"}}, values, "could not get values") - }) - t.Run("templates-path-relative", func(t *testing.T) { - // testcase when loading file from template directory and template file is current working directory - // expected to fail since this is LFI - _, err := generator.loadPayloads(map[string]interface{}{ - "new": "../../../../../../../../../etc/passwd", - }, ".") - require.Error(t, err, "could load payloads") - }) - t.Run("template-directory", func(t *testing.T) { - // testcase when loading file from template directory and template file is inside template directory - // expected to succeed - values, err := generator.loadPayloads(map[string]interface{}{ - "new": fullpath, - }, filepath.Join(templateDir, "test.yaml")) - require.NoError(t, err, "could not load payloads") - require.Equal(t, map[string][]string{"new": {"test", "another"}}, values, "could not get values") - }) - - t.Run("invalid", func(t *testing.T) { - // testcase when loading file from /etc/passwd and template file is at root i.e / - // expected to fail since this is LFI - values, err := generator.loadPayloads(map[string]interface{}{ - "new": "/etc/passwd", - }, "/random") - require.Error(t, err, "could load payloads got %v", values) - require.Equal(t, 0, len(values), "could get values") - - // testcase when loading file from template directory and template file is at root i.e / - // expected to succeed - values, err = generator.loadPayloads(map[string]interface{}{ - "new": fullpath, - }, "/random") - require.NoError(t, err, "could load payloads %v", values) - require.Equal(t, 1, len(values), "could get values") - require.Equal(t, []string{"test", "another"}, values["new"], "could get values") - }) + return &PayloadGenerator{options: opts, catalog: &fakeCatalog{}} } -func TestLoadPayloadsWithAccess(t *testing.T) { - // since we are changing value of global variable i.e templates directory - // run this test as subprocess - if os.Getenv("LOAD_PAYLOAD_WITH_ACCESS") != "1" { - cmd := exec.Command(os.Args[0], "-test.run=TestLoadPayloadsWithAccess") - cmd.Env = append(os.Environ(), "LOAD_PAYLOAD_WITH_ACCESS=1") - err := cmd.Run() - if e, ok := err.(*exec.ExitError); ok && !e.Success() { - return - } - if err != nil { - t.Fatalf("process ran with err %v, want exit status 1", err) - } +func TestLoadPayloads_FastPathFile(t *testing.T) { + g := newTestGenerator() + out, err := g.loadPayloads(map[string]interface{}{"A": "fileA.txt"}, "") + if err != nil { + t.Fatalf("err: %v", err) + } + got := out["A"] + if len(got) != 3 || got[0] != "one" || got[1] != " two" || got[2] != "three" { + t.Fatalf("unexpected: %#v", got) } - templateDir := getTemplatesDir(t) - config.DefaultConfig.SetTemplatesDir(templateDir) - - generator := &PayloadGenerator{catalog: disk.NewCatalog(templateDir), options: getOptions(true)} - - t.Run("no-sandbox-unix", func(t *testing.T) { - if osutils.IsWindows() { - return - } - _, err := generator.loadPayloads(map[string]interface{}{ - "new": "/etc/passwd", - }, "/random") - require.NoError(t, err, "could load payloads") - }) } -func getTemplatesDir(t *testing.T) string { - tempdir, err := os.MkdirTemp("", "templates-*") - require.NoError(t, err, "could not create temp dir") - fullpath := filepath.Join(tempdir, "payloads.txt") - err = os.WriteFile(fullpath, []byte("test\nanother"), 0777) - require.NoError(t, err, "could not write payload") - return tempdir +func TestLoadPayloads_InlineMultiline(t *testing.T) { + g := newTestGenerator() + inline := "a\nb\n" + out, err := g.loadPayloads(map[string]interface{}{"B": inline}, "") + if err != nil { + t.Fatalf("err: %v", err) + } + got := out["B"] + if len(got) != 3 || got[0] != "a" || got[1] != "b" || got[2] != "" { + t.Fatalf("unexpected: %#v", got) + } +} + +func TestLoadPayloads_SingleLineFallsBackToFile(t *testing.T) { + g := newTestGenerator() + inline := "fileA.txt" // single line, should be treated as file path + out, err := g.loadPayloads(map[string]interface{}{"C": inline}, "") + if err != nil { + t.Fatalf("err: %v", err) + } + got := out["C"] + if len(got) != 3 { + t.Fatalf("unexpected len: %d", len(got)) + } +} + +func TestLoadPayloads_InterfaceSlice(t *testing.T) { + g := newTestGenerator() + out, err := g.loadPayloads(map[string]interface{}{"D": []interface{}{"p", "q"}}, "") + if err != nil { + t.Fatalf("err: %v", err) + } + got := out["D"] + if len(got) != 2 || got[0] != "p" || got[1] != "q" { + t.Fatalf("unexpected: %#v", got) + } +} + +func TestLoadPayloadsFromFile_SkipsEmpty(t *testing.T) { + g := newTestGenerator() + rc := io.NopCloser(strings.NewReader("a\n\n\n b \n")) + lines, err := g.loadPayloadsFromFile(rc) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(lines) != 2 || lines[0] != "a" || lines[1] != " b " { + t.Fatalf("unexpected: %#v", lines) + } +} + +func TestValidate_AllowsInlineMultiline(t *testing.T) { + g := newTestGenerator() + inline := "x\ny\n" + if err := g.validate(map[string]interface{}{"E": inline}, ""); err != nil { + t.Fatalf("validate rejected inline multiline: %v", err) + } } diff --git a/pkg/protocols/common/generators/maps_test.go b/pkg/protocols/common/generators/maps_test.go index ca75bb655..8b73539f8 100644 --- a/pkg/protocols/common/generators/maps_test.go +++ b/pkg/protocols/common/generators/maps_test.go @@ -14,3 +14,32 @@ func TestMergeMapsMany(t *testing.T) { "c": {"5"}, }, got, "could not get correct merged map") } + +func TestMergeMapsAndExpand(t *testing.T) { + m1 := map[string]interface{}{"a": "1"} + m2 := map[string]interface{}{"b": "2"} + out := MergeMaps(m1, m2) + if out["a"].(string) != "1" || out["b"].(string) != "2" { + t.Fatalf("unexpected merge: %#v", out) + } + flat := map[string]string{"x": "y"} + exp := ExpandMapValues(flat) + if len(exp["x"]) != 1 || exp["x"][0] != "y" { + t.Fatalf("unexpected expand: %#v", exp) + } +} + +func TestIteratorRemaining(t *testing.T) { + g, err := New(map[string]interface{}{"k": []interface{}{"a", "b"}}, BatteringRamAttack, "", nil, "", nil) + if err != nil { + t.Fatalf("new: %v", err) + } + it := g.NewIterator() + if it.Total() != 2 || it.Remaining() != 2 { + t.Fatalf("unexpected totals: %d %d", it.Total(), it.Remaining()) + } + _, _ = it.Value() + if it.Remaining() != 1 { + t.Fatalf("unexpected remaining after one: %d", it.Remaining()) + } +} diff --git a/pkg/protocols/common/generators/validate.go b/pkg/protocols/common/generators/validate.go index 0aa073714..48365e0db 100644 --- a/pkg/protocols/common/generators/validate.go +++ b/pkg/protocols/common/generators/validate.go @@ -1,7 +1,6 @@ package generators import ( - "errors" "fmt" "path/filepath" "strings" @@ -17,9 +16,8 @@ func (g *PayloadGenerator) validate(payloads map[string]interface{}, templatePat for name, payload := range payloads { switch payloadType := payload.(type) { case string: - // check if it's a multiline string list - if len(strings.Split(payloadType, "\n")) != 1 { - return errors.New("invalid number of lines in payload") + if strings.ContainsRune(payloadType, '\n') { + continue } // For historical reasons, "validate" checks to see if the payload file exist. diff --git a/pkg/protocols/http/build_request.go b/pkg/protocols/http/build_request.go index 0fa8d1502..980573c96 100644 --- a/pkg/protocols/http/build_request.go +++ b/pkg/protocols/http/build_request.go @@ -92,9 +92,8 @@ type generatedRequest struct { // setReqURLPattern sets the url request pattern for the generated request func (gr *generatedRequest) setReqURLPattern(reqURLPattern string) { - data := strings.Split(reqURLPattern, "\n") - if len(data) > 1 { - reqURLPattern = strings.TrimSpace(data[0]) + if idx := strings.IndexByte(reqURLPattern, '\n'); idx >= 0 { + reqURLPattern = strings.TrimSpace(reqURLPattern[:idx]) // this is raw request (if it has 3 parts after strings.Fields then its valid only use 2nd part) parts := strings.Fields(reqURLPattern) if len(parts) >= 3 { diff --git a/pkg/protocols/http/raw/raw.go b/pkg/protocols/http/raw/raw.go index c2a2121b6..7b1457afa 100644 --- a/pkg/protocols/http/raw/raw.go +++ b/pkg/protocols/http/raw/raw.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "strings" + "sync" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/authprovider/authx" @@ -17,6 +18,8 @@ import ( urlutil "github.com/projectdiscovery/utils/url" ) +var bufferPool = sync.Pool{New: func() any { return new(bytes.Buffer) }} + // Request defines a basic HTTP raw request type Request struct { FullURL string @@ -270,13 +273,17 @@ func (r *Request) TryFillCustomHeaders(headers []string) error { if newLineIndex > 0 { newLineIndex += hostHeaderIndex + 2 // insert custom headers - var buf bytes.Buffer + buf := bufferPool.Get().(*bytes.Buffer) + buf.Reset() buf.Write(r.UnsafeRawBytes[:newLineIndex]) for _, header := range headers { - buf.WriteString(fmt.Sprintf("%s\r\n", header)) + buf.WriteString(header) + buf.WriteString("\r\n") } buf.Write(r.UnsafeRawBytes[newLineIndex:]) - r.UnsafeRawBytes = buf.Bytes() + r.UnsafeRawBytes = append([]byte(nil), buf.Bytes()...) + buf.Reset() + bufferPool.Put(buf) return nil } return errors.New("no new line found at the end of host header") @@ -301,9 +308,10 @@ func (r *Request) ApplyAuthStrategy(strategy authx.AuthStrategy) { parsed.Params.Add(p.Key, p.Value) } case *authx.CookiesAuthStrategy: - var buff bytes.Buffer + buff := bufferPool.Get().(*bytes.Buffer) + buff.Reset() for _, cookie := range s.Data.Cookies { - buff.WriteString(fmt.Sprintf("%s=%s; ", cookie.Key, cookie.Value)) + fmt.Fprintf(buff, "%s=%s; ", cookie.Key, cookie.Value) } if buff.Len() > 0 { if val, ok := r.Headers["Cookie"]; ok { @@ -312,6 +320,7 @@ func (r *Request) ApplyAuthStrategy(strategy authx.AuthStrategy) { r.Headers["Cookie"] = buff.String() } } + bufferPool.Put(buff) case *authx.HeadersAuthStrategy: for _, header := range s.Data.Headers { r.Headers[header.Key] = header.Value diff --git a/pkg/protocols/http/raw/raw_test.go b/pkg/protocols/http/raw/raw_test.go index a44664d48..80fefff7f 100644 --- a/pkg/protocols/http/raw/raw_test.go +++ b/pkg/protocols/http/raw/raw_test.go @@ -7,6 +7,21 @@ import ( "github.com/stretchr/testify/require" ) +func TestTryFillCustomHeaders_BufferDetached(t *testing.T) { + r := &Request{ + UnsafeRawBytes: []byte("GET / HTTP/1.1\r\nHost: example.com\r\n\r\nBody"), + } + // first fill + err := r.TryFillCustomHeaders([]string{"X-Test: 1"}) + require.NoError(t, err, "unexpected error on first call") + prev := r.UnsafeRawBytes + prevStr := string(prev) // content snapshot + err = r.TryFillCustomHeaders([]string{"X-Another: 2"}) + require.NoError(t, err, "unexpected error on second call") + require.Equal(t, prevStr, string(prev), "first slice mutated after second call; buffer not detached") + require.NotEqual(t, prevStr, string(r.UnsafeRawBytes), "request bytes did not change after second call") +} + func TestParseRawRequestWithPort(t *testing.T) { request, err := Parse(`GET /gg/phpinfo.php HTTP/1.1 Host: {{Hostname}}:123 diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index 381f4d385..c6e3de4d9 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -240,6 +240,48 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV } }) + // bounded worker-pool to avoid spawning one goroutine per payload + type task struct { + req *generatedRequest + updatedInput *contextargs.Context + } + + var workersWg sync.WaitGroup + currentWorkers := maxWorkers + tasks := make(chan task, maxWorkers) + spawnWorker := func(ctx context.Context) { + workersWg.Add(1) + go func() { + defer workersWg.Done() + for t := range tasks { + select { + case <-ctx.Done(): + return + default: + } + if spmHandler.FoundFirstMatch() || request.isUnresponsiveAddress(t.updatedInput) || spmHandler.Cancelled() { + continue + } + spmHandler.Acquire() + if spmHandler.FoundFirstMatch() || request.isUnresponsiveAddress(t.updatedInput) || spmHandler.Cancelled() { + spmHandler.Release() + continue + } + request.options.RateLimitTake() + select { + case <-spmHandler.Done(): + spmHandler.Release() + continue + case spmHandler.ResultChan <- request.executeRequest(t.updatedInput, t.req, make(map[string]interface{}), false, wrappedCallback, 0): + spmHandler.Release() + } + } + }() + } + for i := 0; i < currentWorkers; i++ { + spawnWorker(ctx) + } + // iterate payloads and make requests generator := request.newGenerator(false) for { @@ -259,6 +301,13 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV if err := spmHandler.Resize(input.Context(), request.options.Options.PayloadConcurrency); err != nil { return err } + // if payload concurrency increased, add more workers + if spmHandler.Size() > currentWorkers { + for i := 0; i < spmHandler.Size()-currentWorkers; i++ { + spawnWorker(ctx) + } + currentWorkers = spmHandler.Size() + } } // break if stop at first match is found or host is unresponsive @@ -284,29 +333,21 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV spmHandler.Cancel() return nil } - spmHandler.Acquire() - go func(httpRequest *generatedRequest) { - defer spmHandler.Release() - if spmHandler.FoundFirstMatch() || request.isUnresponsiveAddress(updatedInput) || spmHandler.Cancelled() { - return + select { + case <-spmHandler.Done(): + close(tasks) + workersWg.Wait() + spmHandler.Wait() + if spmHandler.FoundFirstMatch() { + return nil } - // putting ratelimiter here prevents any unnecessary waiting if any - request.options.RateLimitTake() - - // after ratelimit take, check if we need to stop - if spmHandler.FoundFirstMatch() || request.isUnresponsiveAddress(updatedInput) || spmHandler.Cancelled() { - return - } - - select { - case <-spmHandler.Done(): - return - case spmHandler.ResultChan <- request.executeRequest(input, httpRequest, make(map[string]interface{}), false, wrappedCallback, 0): - return - } - }(generatedHttpRequest) + return multierr.Combine(spmHandler.CombinedResults()...) + case tasks <- task{req: generatedHttpRequest, updatedInput: updatedInput}: + } request.options.Progress.IncrementRequests() } + close(tasks) + workersWg.Wait() spmHandler.Wait() if spmHandler.FoundFirstMatch() { // ignore any context cancellation and in-transit execution errors diff --git a/pkg/protocols/http/request_test.go b/pkg/protocols/http/request_test.go index a6314ae5a..b547d91b5 100644 --- a/pkg/protocols/http/request_test.go +++ b/pkg/protocols/http/request_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "sync/atomic" "testing" "github.com/stretchr/testify/require" @@ -257,3 +258,116 @@ func TestReqURLPattern(t *testing.T) { require.NotEmpty(t, finalEvent.Results[0].ReqURLPattern, "could not get req url pattern") require.Equal(t, `/{{rand_char("abc")}}/{{interactsh-url}}/123?query={{rand_int(1, 10)}}&data={{randstr}}`, finalEvent.Results[0].ReqURLPattern) } + +// fakeHostErrorsCache implements hosterrorscache.CacheInterface minimally for tests +type fakeHostErrorsCache struct{} + +func (f *fakeHostErrorsCache) SetVerbose(bool) {} +func (f *fakeHostErrorsCache) Close() {} +func (f *fakeHostErrorsCache) Remove(*contextargs.Context) {} +func (f *fakeHostErrorsCache) MarkFailed(string, *contextargs.Context, error) {} +func (f *fakeHostErrorsCache) MarkFailedOrRemove(string, *contextargs.Context, error) { +} + +// Check always returns true to simulate an already unresponsive host +func (f *fakeHostErrorsCache) Check(string, *contextargs.Context) bool { return true } + +func TestExecuteParallelHTTP_StopAtFirstMatch(t *testing.T) { + options := testutils.DefaultOptions + testutils.Init(options) + + // server that always matches + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = fmt.Fprintf(w, "match") + })) + defer ts.Close() + + templateID := "parallel-stop-first" + req := &Request{ + ID: templateID, + Method: HTTPMethodTypeHolder{MethodType: HTTPGet}, + Path: []string{"{{BaseURL}}/p?x={{v}}"}, + Threads: 2, + Payloads: map[string]interface{}{ + "v": []string{"1", "2"}, + }, + Operators: operators.Operators{ + Matchers: []*matchers.Matcher{{ + Part: "body", + Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher}, + Words: []string{"match"}, + }}, + }, + StopAtFirstMatch: true, + } + + executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{ + ID: templateID, + Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"}, + }) + err := req.Compile(executerOpts) + require.NoError(t, err) + + var matches int32 + metadata := make(output.InternalEvent) + previous := make(output.InternalEvent) + ctxArgs := contextargs.NewWithInput(context.Background(), ts.URL) + err = req.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) { + if event.OperatorsResult != nil && event.OperatorsResult.Matched { + atomic.AddInt32(&matches, 1) + } + }) + require.NoError(t, err) + require.Equal(t, int32(1), atomic.LoadInt32(&matches), "expected only first match to be processed") +} + +func TestExecuteParallelHTTP_SkipOnUnresponsiveFromCache(t *testing.T) { + options := testutils.DefaultOptions + testutils.Init(options) + + // server that would match if reached + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = fmt.Fprintf(w, "match") + })) + defer ts.Close() + + templateID := "parallel-skip-unresponsive" + req := &Request{ + ID: templateID, + Method: HTTPMethodTypeHolder{MethodType: HTTPGet}, + Path: []string{"{{BaseURL}}/p?x={{v}}"}, + Threads: 2, + Payloads: map[string]interface{}{ + "v": []string{"1", "2"}, + }, + Operators: operators.Operators{ + Matchers: []*matchers.Matcher{{ + Part: "body", + Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher}, + Words: []string{"match"}, + }}, + }, + } + + executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{ + ID: templateID, + Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"}, + }) + // inject fake host errors cache that forces skip + executerOpts.HostErrorsCache = &fakeHostErrorsCache{} + + err := req.Compile(executerOpts) + require.NoError(t, err) + + var matches int32 + metadata := make(output.InternalEvent) + previous := make(output.InternalEvent) + ctxArgs := contextargs.NewWithInput(context.Background(), ts.URL) + err = req.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) { + if event.OperatorsResult != nil && event.OperatorsResult.Matched { + atomic.AddInt32(&matches, 1) + } + }) + require.NoError(t, err) + require.Equal(t, int32(0), atomic.LoadInt32(&matches), "expected no matches when host is marked unresponsive") +} diff --git a/pkg/protocols/javascript/js.go b/pkg/protocols/javascript/js.go index 9925c3103..8b872d84a 100644 --- a/pkg/protocols/javascript/js.go +++ b/pkg/protocols/javascript/js.go @@ -811,8 +811,11 @@ func beautifyJavascript(code string) string { } func prettyPrint(templateId string, buff string) { + if buff == "" { + return + } lines := strings.Split(buff, "\n") - final := []string{} + final := make([]string, 0, len(lines)) for _, v := range lines { if v != "" { final = append(final, "\t"+v) diff --git a/pkg/reporting/reporting.go b/pkg/reporting/reporting.go index c3706c970..58d7f61fb 100644 --- a/pkg/reporting/reporting.go +++ b/pkg/reporting/reporting.go @@ -192,11 +192,13 @@ func New(options *Options, db string, doNotDedupe bool) (Client, error) { } } - storage, err := dedupe.New(db) - if err != nil { - return nil, err + if db != "" || len(client.trackers) > 0 || len(client.exporters) > 0 { + storage, err := dedupe.New(db) + if err != nil { + return nil, err + } + client.dedupe = storage } - client.dedupe = storage return client, nil } diff --git a/pkg/templates/cache.go b/pkg/templates/cache.go index b4c00fb36..ae7124772 100644 --- a/pkg/templates/cache.go +++ b/pkg/templates/cache.go @@ -12,7 +12,9 @@ type Cache struct { // New returns a new templates cache func NewCache() *Cache { - return &Cache{items: mapsutil.NewSyncLockMap[string, parsedTemplate]()} + return &Cache{ + items: mapsutil.NewSyncLockMap[string, parsedTemplate](), + } } type parsedTemplate struct { @@ -33,7 +35,31 @@ func (t *Cache) Has(template string) (*Template, []byte, error) { // Store stores a template with data and error func (t *Cache) Store(id string, tpl *Template, raw []byte, err error) { - _ = t.items.Set(id, parsedTemplate{template: tpl, raw: conversion.String(raw), err: err}) + entry := parsedTemplate{ + template: tpl, + err: err, + raw: conversion.String(raw), + } + _ = t.items.Set(id, entry) +} + +// StoreWithoutRaw stores a template without raw data for memory efficiency +func (t *Cache) StoreWithoutRaw(id string, tpl *Template, err error) { + entry := parsedTemplate{ + template: tpl, + err: err, + raw: "", + } + _ = t.items.Set(id, entry) +} + +// Get returns only the template without raw bytes +func (t *Cache) Get(id string) (*Template, error) { + value, ok := t.items.Get(id) + if !ok { + return nil, nil + } + return value.template, value.err } // Purge the cache diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index 74818557e..9907e2711 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -404,7 +404,7 @@ func (template *Template) ImportFileRefs(options *protocols.ExecutorOptions) err // for code protocol requests for _, request := range template.RequestsCode { // simple test to check if source is a file or a snippet - if len(strings.Split(request.Source, "\n")) == 1 && fileutil.FileExists(request.Source) { + if !strings.ContainsRune(request.Source, '\n') && fileutil.FileExists(request.Source) { if val, ok := loadFile(request.Source); ok { template.ImportedFiles = append(template.ImportedFiles, request.Source) request.Source = val @@ -415,7 +415,7 @@ func (template *Template) ImportFileRefs(options *protocols.ExecutorOptions) err // for javascript protocol code references for _, request := range template.RequestsJavascript { // simple test to check if source is a file or a snippet - if len(strings.Split(request.Code, "\n")) == 1 && fileutil.FileExists(request.Code) { + if !strings.ContainsRune(request.Code, '\n') && fileutil.FileExists(request.Code) { if val, ok := loadFile(request.Code); ok { template.ImportedFiles = append(template.ImportedFiles, request.Code) request.Code = val @@ -442,7 +442,7 @@ func (template *Template) ImportFileRefs(options *protocols.ExecutorOptions) err if req.Type() == types.CodeProtocol { request := req.(*code.Request) // simple test to check if source is a file or a snippet - if len(strings.Split(request.Source, "\n")) == 1 && fileutil.FileExists(request.Source) { + if !strings.ContainsRune(request.Source, '\n') && fileutil.FileExists(request.Source) { if val, ok := loadFile(request.Source); ok { template.ImportedFiles = append(template.ImportedFiles, request.Source) request.Source = val @@ -456,7 +456,7 @@ func (template *Template) ImportFileRefs(options *protocols.ExecutorOptions) err if req.Type() == types.JavascriptProtocol { request := req.(*javascript.Request) // simple test to check if source is a file or a snippet - if len(strings.Split(request.Code, "\n")) == 1 && fileutil.FileExists(request.Code) { + if !strings.ContainsRune(request.Code, '\n') && fileutil.FileExists(request.Code) { if val, ok := loadFile(request.Code); ok { template.ImportedFiles = append(template.ImportedFiles, request.Code) request.Code = val diff --git a/pkg/templates/templates_test.go b/pkg/templates/templates_test.go index 7621f1c57..a94ebf656 100644 --- a/pkg/templates/templates_test.go +++ b/pkg/templates/templates_test.go @@ -9,6 +9,32 @@ import ( "gopkg.in/yaml.v2" ) +func TestCachePoolZeroing(t *testing.T) { + c := NewCache() + + tpl := &Template{ID: "x"} + raw := []byte("SOME BIG RAW") + + c.Store("id1", tpl, raw, nil) + gotTpl, gotErr := c.Get("id1") + if gotErr != nil { + t.Fatalf("unexpected err: %v", gotErr) + } + if gotTpl == nil || gotTpl.ID != "x" { + t.Fatalf("unexpected tpl: %#v", gotTpl) + } + + // StoreWithoutRaw should not retain raw + c.StoreWithoutRaw("id2", tpl, nil) + gotTpl2, gotErr2 := c.Get("id2") + if gotErr2 != nil { + t.Fatalf("unexpected err: %v", gotErr2) + } + if gotTpl2 == nil || gotTpl2.ID != "x" { + t.Fatalf("unexpected tpl2: %#v", gotTpl2) + } +} + func TestTemplateStruct(t *testing.T) { templatePath := "./tests/match-1.yaml" bin, err := os.ReadFile(templatePath) From 792998d8e288c096bca00d55adf778d549b85abc Mon Sep 17 00:00:00 2001 From: halcyondream <107806954+halcyondream@users.noreply.github.com> Date: Mon, 15 Sep 2025 19:05:00 -0400 Subject: [PATCH 128/135] Refactored header-based auth scans not to normalize the header names. (#6479) * Refactored header-based auth scans not to normalize the header names. * Removed the header validation as it's not really useful here. * adding docs --------- Co-authored-by: Mzack9999 --- README.md | 1 + SYNTAX-REFERENCE.md | 4 ++++ pkg/authprovider/authx/file.go | 4 ++-- pkg/authprovider/authx/headers_auth.go | 8 ++++++-- pkg/authprovider/authx/testData/example-auth.yaml | 4 ++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 741ceafc3..490b60709 100644 --- a/README.md +++ b/README.md @@ -356,6 +356,7 @@ CLOUD: AUTHENTICATION: -sf, -secret-file string[] path to config file containing secrets for nuclei authenticated scan -ps, -prefetch-secrets prefetch secrets from the secrets file + # NOTE: Headers in secrets files preserve exact casing (useful for case-sensitive APIs) EXAMPLES: diff --git a/SYNTAX-REFERENCE.md b/SYNTAX-REFERENCE.md index 24cbd04d3..399c25a93 100755 --- a/SYNTAX-REFERENCE.md +++ b/SYNTAX-REFERENCE.md @@ -1194,6 +1194,8 @@ be provided as payload which will be read on run-time. Headers contains HTTP Headers to send with the request. +**Note:** When using headers in authentication secrets files (via `-sf` flag), header names preserve exact casing (e.g., `barAuthToken` stays as `barAuthToken`). This is useful for APIs that require case-sensitive header names. Template headers are canonicalized by default. + Examples: @@ -1424,6 +1426,8 @@ Valid values: SkipSecretFile skips the authentication or authorization configured in the secret file. +**Note:** Authentication secrets files preserve exact header casing, which is useful for case-sensitive APIs. +
diff --git a/pkg/authprovider/authx/file.go b/pkg/authprovider/authx/file.go index 804b6c340..655039b9e 100644 --- a/pkg/authprovider/authx/file.go +++ b/pkg/authprovider/authx/file.go @@ -55,7 +55,7 @@ type Secret struct { Type string `json:"type" yaml:"type"` Domains []string `json:"domains" yaml:"domains"` DomainsRegex []string `json:"domains-regex" yaml:"domains-regex"` - Headers []KV `json:"headers" yaml:"headers"` + Headers []KV `json:"headers" yaml:"headers"` // Headers preserve exact casing (useful for case-sensitive APIs) Cookies []Cookie `json:"cookies" yaml:"cookies"` Params []KV `json:"params" yaml:"params"` Username string `json:"username" yaml:"username"` // can be either email or username @@ -148,7 +148,7 @@ func (s *Secret) Validate() error { } type KV struct { - Key string `json:"key" yaml:"key"` + Key string `json:"key" yaml:"key"` // Header key (preserves exact casing) Value string `json:"value" yaml:"value"` } diff --git a/pkg/authprovider/authx/headers_auth.go b/pkg/authprovider/authx/headers_auth.go index b3ede114d..d474f75bd 100644 --- a/pkg/authprovider/authx/headers_auth.go +++ b/pkg/authprovider/authx/headers_auth.go @@ -21,15 +21,19 @@ func NewHeadersAuthStrategy(data *Secret) *HeadersAuthStrategy { } // Apply applies the headers auth strategy to the request +// NOTE: This preserves exact header casing (e.g., barAuthToken stays as barAuthToken) +// This is useful for APIs that require case-sensitive header names func (s *HeadersAuthStrategy) Apply(req *http.Request) { for _, header := range s.Data.Headers { - req.Header.Set(header.Key, header.Value) + req.Header[header.Key] = []string{header.Value} } } // ApplyOnRR applies the headers auth strategy to the retryable request +// NOTE: This preserves exact header casing (e.g., barAuthToken stays as barAuthToken) +// This is useful for APIs that require case-sensitive header names func (s *HeadersAuthStrategy) ApplyOnRR(req *retryablehttp.Request) { for _, header := range s.Data.Headers { - req.Header.Set(header.Key, header.Value) + req.Header[header.Key] = []string{header.Value} } } diff --git a/pkg/authprovider/authx/testData/example-auth.yaml b/pkg/authprovider/authx/testData/example-auth.yaml index 0c3175090..0f64a2798 100644 --- a/pkg/authprovider/authx/testData/example-auth.yaml +++ b/pkg/authprovider/authx/testData/example-auth.yaml @@ -12,6 +12,8 @@ info: # static secrets static: # for header based auth session + # NOTE: Headers preserve exact casing (e.g., x-pdcp-key stays as x-pdcp-key) + # This is useful for APIs that require case-sensitive header names - type: header domains: - api.projectdiscovery.io @@ -20,6 +22,8 @@ static: headers: - key: x-pdcp-key value: + - key: barAuthToken + value: # for query based auth session - type: Query From f610ed4cabc8d672509e590baf8a8d750728b3df Mon Sep 17 00:00:00 2001 From: ghost Date: Mon, 15 Sep 2025 23:06:45 +0000 Subject: [PATCH 129/135] =?UTF-8?q?docs:=20update=20syntax=20&=20JSON=20sc?= =?UTF-8?q?hema=20=F0=9F=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SYNTAX-REFERENCE.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SYNTAX-REFERENCE.md b/SYNTAX-REFERENCE.md index 399c25a93..24cbd04d3 100755 --- a/SYNTAX-REFERENCE.md +++ b/SYNTAX-REFERENCE.md @@ -1194,8 +1194,6 @@ be provided as payload which will be read on run-time. Headers contains HTTP Headers to send with the request. -**Note:** When using headers in authentication secrets files (via `-sf` flag), header names preserve exact casing (e.g., `barAuthToken` stays as `barAuthToken`). This is useful for APIs that require case-sensitive header names. Template headers are canonicalized by default. - Examples: @@ -1426,8 +1424,6 @@ Valid values: SkipSecretFile skips the authentication or authorization configured in the secret file. -**Note:** Authentication secrets files preserve exact header casing, which is useful for case-sensitive APIs. -
From 0ea42e5f66bb9f1ae5e47a3c46eb250a726113c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 05:03:03 +0000 Subject: [PATCH 130/135] chore(deps): bump the modules group with 6 updates Bumps the modules group with 6 updates: | Package | From | To | | --- | --- | --- | | [github.com/projectdiscovery/fastdialer](https://github.com/projectdiscovery/fastdialer) | `0.4.10` | `0.4.11` | | [github.com/projectdiscovery/retryablehttp-go](https://github.com/projectdiscovery/retryablehttp-go) | `1.0.124` | `1.0.125` | | [github.com/projectdiscovery/gologger](https://github.com/projectdiscovery/gologger) | `1.1.54` | `1.1.55` | | [github.com/projectdiscovery/networkpolicy](https://github.com/projectdiscovery/networkpolicy) | `0.1.24` | `0.1.25` | | [github.com/projectdiscovery/wappalyzergo](https://github.com/projectdiscovery/wappalyzergo) | `0.2.46` | `0.2.47` | | [github.com/projectdiscovery/cdncheck](https://github.com/projectdiscovery/cdncheck) | `1.1.36` | `1.2.0` | Updates `github.com/projectdiscovery/fastdialer` from 0.4.10 to 0.4.11 - [Release notes](https://github.com/projectdiscovery/fastdialer/releases) - [Commits](https://github.com/projectdiscovery/fastdialer/compare/v0.4.10...v0.4.11) Updates `github.com/projectdiscovery/retryablehttp-go` from 1.0.124 to 1.0.125 - [Release notes](https://github.com/projectdiscovery/retryablehttp-go/releases) - [Commits](https://github.com/projectdiscovery/retryablehttp-go/compare/v1.0.124...v1.0.125) Updates `github.com/projectdiscovery/gologger` from 1.1.54 to 1.1.55 - [Release notes](https://github.com/projectdiscovery/gologger/releases) - [Commits](https://github.com/projectdiscovery/gologger/compare/v1.1.54...v1.1.55) Updates `github.com/projectdiscovery/networkpolicy` from 0.1.24 to 0.1.25 - [Release notes](https://github.com/projectdiscovery/networkpolicy/releases) - [Commits](https://github.com/projectdiscovery/networkpolicy/compare/v0.1.24...v0.1.25) Updates `github.com/projectdiscovery/wappalyzergo` from 0.2.46 to 0.2.47 - [Release notes](https://github.com/projectdiscovery/wappalyzergo/releases) - [Commits](https://github.com/projectdiscovery/wappalyzergo/compare/v0.2.46...v0.2.47) Updates `github.com/projectdiscovery/cdncheck` from 1.1.36 to 1.2.0 - [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.36...v1.2.0) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/fastdialer dependency-version: 0.4.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/retryablehttp-go dependency-version: 1.0.125 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/gologger dependency-version: 1.1.55 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/networkpolicy dependency-version: 0.1.25 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/wappalyzergo dependency-version: 0.2.47 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: modules - dependency-name: github.com/projectdiscovery/cdncheck dependency-version: 1.2.0 dependency-type: indirect update-type: version-update:semver-minor dependency-group: modules ... Signed-off-by: dependabot[bot] --- go.mod | 22 +++++++++++----------- go.sum | 44 ++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index a9d03e62a..cfb19222c 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,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.10 + github.com/projectdiscovery/fastdialer v0.4.11 github.com/projectdiscovery/hmap v0.0.94 github.com/projectdiscovery/interactsh v1.2.4 github.com/projectdiscovery/rawhttp v0.1.90 github.com/projectdiscovery/retryabledns v1.0.107 - github.com/projectdiscovery/retryablehttp-go v1.0.124 + github.com/projectdiscovery/retryablehttp-go v1.0.125 github.com/projectdiscovery/yamldoc-go v1.0.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/rs/xid v1.6.0 @@ -39,7 +39,7 @@ require ( github.com/valyala/fasttemplate v1.2.2 github.com/weppos/publicsuffix-go v0.50.0 go.uber.org/multierr v1.11.0 - golang.org/x/net v0.43.0 + golang.org/x/net v0.44.0 golang.org/x/oauth2 v0.30.0 golang.org/x/text v0.29.0 gopkg.in/yaml.v2 v2.4.0 @@ -96,13 +96,13 @@ require ( github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb github.com/projectdiscovery/goflags v0.1.74 - github.com/projectdiscovery/gologger v1.1.54 + github.com/projectdiscovery/gologger v1.1.55 github.com/projectdiscovery/gostruct v0.0.2 github.com/projectdiscovery/gozero v0.1.0 github.com/projectdiscovery/httpx v1.7.2-0.20250911192144-fc425deb041a github.com/projectdiscovery/mapcidr v1.1.34 github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 - github.com/projectdiscovery/networkpolicy v0.1.24 + github.com/projectdiscovery/networkpolicy v0.1.25 github.com/projectdiscovery/ratelimit v0.0.82 github.com/projectdiscovery/rdap v0.9.0 github.com/projectdiscovery/sarif v0.0.1 @@ -110,7 +110,7 @@ require ( github.com/projectdiscovery/uncover v1.1.0 github.com/projectdiscovery/useragent v0.0.101 github.com/projectdiscovery/utils v0.5.0 - github.com/projectdiscovery/wappalyzergo v0.2.46 + github.com/projectdiscovery/wappalyzergo v0.2.47 github.com/redis/go-redis/v9 v9.11.0 github.com/seh-msft/burpxml v1.0.1 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -123,7 +123,7 @@ require ( github.com/zmap/zgrab2 v0.1.8 gitlab.com/gitlab-org/api/client-go v0.130.1 go.mongodb.org/mongo-driver v1.17.4 - golang.org/x/term v0.34.0 + golang.org/x/term v0.35.0 gopkg.in/yaml.v3 v3.0.1 moul.io/http2curl v1.0.0 ) @@ -213,7 +213,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // 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.24.0 // indirect + github.com/gaissmai/bart v0.25.0 // 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 @@ -318,7 +318,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect github.com/projectdiscovery/blackrock v0.0.1 // indirect - github.com/projectdiscovery/cdncheck v1.1.36 // indirect + github.com/projectdiscovery/cdncheck v1.2.0 // indirect 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 @@ -393,10 +393,10 @@ require ( go.etcd.io/bbolt v1.4.0 // indirect go.uber.org/zap v1.27.0 // indirect goftp.io/server/v2 v2.0.1 // indirect - golang.org/x/crypto v0.41.0 // indirect + golang.org/x/crypto v0.42.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b golang.org/x/mod v0.27.0 // indirect - golang.org/x/sys v0.35.0 // indirect + golang.org/x/sys v0.36.0 // indirect golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.36.0 google.golang.org/protobuf v1.36.6 // indirect diff --git a/go.sum b/go.sum index 5838a14bd..1ad6e6aba 100644 --- a/go.sum +++ b/go.sum @@ -657,8 +657,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.24.0 h1:HOq5aXDBa4d376KkuxD+xnS9DQWWJtD4zgDNoGV0KrQ= -github.com/gaissmai/bart v0.24.0/go.mod h1:RpLtt3lWq1BoRz3AAyDAJ7jhLWBkYhVCfi+ximB2t68= +github.com/gaissmai/bart v0.25.0 h1:eqiokVPqM3F94vJ0bTHXHtH91S8zkKL+bKh+BsGOsJM= +github.com/gaissmai/bart v0.25.0/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c= 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= @@ -1249,14 +1249,14 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss= -github.com/projectdiscovery/cdncheck v1.1.36 h1:SIQHfBL1Kg+ydWxQV6QsMBvVLsiNdI+kQM25zGtw+Bc= -github.com/projectdiscovery/cdncheck v1.1.36/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U= +github.com/projectdiscovery/cdncheck v1.2.0 h1:KzBk+U7w7vQ5y//pCfynQq8qxnFbf2XFmjGltmPJogs= +github.com/projectdiscovery/cdncheck v1.2.0/go.mod h1:dSyW7D7ItsBp9dRoBh2JrL/s16lZkToUN2XvODNSGjA= github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE= github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= github.com/projectdiscovery/dsl v0.7.0 h1:tfZcsVCoujXvJq2AtplMUWdSvYcQt81uDcNCfHzTLC8= github.com/projectdiscovery/dsl v0.7.0/go.mod h1:tRkJQglLwBjaH9Z5wcf/zZOafo+G1TyrhKV6CtQnD4k= -github.com/projectdiscovery/fastdialer v0.4.10 h1:hbiB+1/xrlC3K5+dMIQgtyGB3tvnLt/QiRSFAEDb/g8= -github.com/projectdiscovery/fastdialer v0.4.10/go.mod h1:i3dKsXReeOWAkmY27+aenewBZtHZHJCyIrw1oF8aTFQ= +github.com/projectdiscovery/fastdialer v0.4.11 h1:6JYoORInQiENFPTqGMI+1GaL5hOTD/sjWrSbzM8d+Z0= +github.com/projectdiscovery/fastdialer v0.4.11/go.mod h1:i2dB26BHw0BMrx7ccbHcb/1LE5q9gy0ojvBytATl38E= 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= @@ -1267,8 +1267,8 @@ github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG90 github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY= github.com/projectdiscovery/goflags v0.1.74 h1:n85uTRj5qMosm0PFBfsvOL24I7TdWRcWq/1GynhXS7c= github.com/projectdiscovery/goflags v0.1.74/go.mod h1:UMc9/7dFz2oln+10tv6cy+7WZKTHf9UGhaNkF95emh4= -github.com/projectdiscovery/gologger v1.1.54 h1:WMzvJ8j/4gGfPKpCttSTaYCVDU1MWQSJnk3wU8/U6Ws= -github.com/projectdiscovery/gologger v1.1.54/go.mod h1:vza/8pe2OKOt+ujFWncngknad1XWr8EnLKlbcejOyUE= +github.com/projectdiscovery/gologger v1.1.55 h1:ASHPXrDyyvFSRMpWXK/UptujU/KwDGgVGbn9BhF8azo= +github.com/projectdiscovery/gologger v1.1.55/go.mod h1:RtAcBG7KzTWmAEVEVWiBbKGKsYpqzxKXzn3yhAFkfic= github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M= github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE= github.com/projectdiscovery/gozero v0.1.0 h1:QC+WPEsEVFtPmAm9FiIVT/obv9rF/pS2mnag8zXIAQI= @@ -1287,8 +1287,8 @@ 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.24 h1:1EvBsUeKvuSVJpRR64Jf4T8852df/O7qXIFsKs/PU3o= -github.com/projectdiscovery/networkpolicy v0.1.24/go.mod h1:DEktWhDxgsQ4hrvz00XQ0GPFSFkxsD6XBOOiVUKXGuo= +github.com/projectdiscovery/networkpolicy v0.1.25 h1:2f3Nxp4ncz/95hm6PkIDLcjMJI6ei2YsgkQ29NZn7b0= +github.com/projectdiscovery/networkpolicy v0.1.25/go.mod h1:6zQPoZRyGeNq0WvWnL5cbah3mCg9KJiOn5tgVQWGIn4= github.com/projectdiscovery/ratelimit v0.0.82 h1:rtO5SQf5uQFu5zTahTaTcO06OxmG8EIF1qhdFPIyTak= github.com/projectdiscovery/ratelimit v0.0.82/go.mod h1:z076BrLkBb5yS7uhHNoCTf8X/BvFSGRxwQ8EzEL9afM= github.com/projectdiscovery/rawhttp v0.1.90 h1:LOSZ6PUH08tnKmWsIwvwv1Z/4zkiYKYOSZ6n+8RFKtw= @@ -1297,8 +1297,8 @@ github.com/projectdiscovery/rdap v0.9.0 h1:wPhHx5pQ2QI+WGhyNb2PjhTl0NtB39Nk7YFZ9 github.com/projectdiscovery/rdap v0.9.0/go.mod h1:zk4yrJFQ2Hy36Aqk+DvotYQxYAeALaCJ5ORySkff36Q= github.com/projectdiscovery/retryabledns v1.0.107 h1:Rd1JK7hfL68xRg3RzXmw9Q6B6WSNv9bdPhUoGvvebyg= github.com/projectdiscovery/retryabledns v1.0.107/go.mod h1:XddeOhDpwS0qR8/T4GXRGgDQsLhtRHw3TRdMsgJs28o= -github.com/projectdiscovery/retryablehttp-go v1.0.124 h1:GC70rH6G+u60SolTRx1fqtI7FGHQddafWLjPOCj2Q0c= -github.com/projectdiscovery/retryablehttp-go v1.0.124/go.mod h1:wF3ct9VjSVkmd2TAzqIZzbu+e/2/qfPaw/dWyjf+aLE= +github.com/projectdiscovery/retryablehttp-go v1.0.125 h1:/00K0xHXIRLn2awpn6RD66rzBUyGfweHmtrGeDyKWok= +github.com/projectdiscovery/retryablehttp-go v1.0.125/go.mod h1:69TkYApUaekghXT1TJxiwKLdEY1xO+H7RCDsHx5eKWg= 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= @@ -1311,8 +1311,8 @@ github.com/projectdiscovery/useragent v0.0.101 h1:8A+XOJ/nIH+WqW8ogLxJ/psemGp8AT github.com/projectdiscovery/useragent v0.0.101/go.mod h1:RGoRw1BQ/lJnhYMbMpEKjyAAgCaDCr/+GsULo5yEJ2I= github.com/projectdiscovery/utils v0.5.0 h1:DN7mg2DpyObLByuObXzAFEkdNRDoPUnqE5N2szd3b3c= github.com/projectdiscovery/utils v0.5.0/go.mod h1:eCAWMmyaNxyPWbiKv1oeYJLIKpxceHE2+NWx3Jodhqk= -github.com/projectdiscovery/wappalyzergo v0.2.46 h1:vvHsIl8c+pM6jsbwF5zuspJrjBDEDUoEY/FqBP2SFn4= -github.com/projectdiscovery/wappalyzergo v0.2.46/go.mod h1:1dHfTJRhrbbWBdKwl1p4QKpUDNnPYlHBBL7rEwCDdjM= +github.com/projectdiscovery/wappalyzergo v0.2.47 h1:8cqpgVfby3AlnYDDDFUkuEZRvYCmVZvrKLxSnf09j1Q= +github.com/projectdiscovery/wappalyzergo v0.2.47/go.mod h1:kPzB+L3ISGO5m8u5fukjlF5FJFJ1NLV86emOx+k3AVU= github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas= github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1696,8 +1696,8 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1849,8 +1849,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2033,8 +2033,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -2064,8 +2064,8 @@ golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 39e9286371b7250a662ea96f66811af50413bb3a Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 22 Sep 2025 18:19:56 +0200 Subject: [PATCH 131/135] Feat 6231 deadlock (#6469) * fixing recursive deadlock * using atomics * fixing init --- pkg/authprovider/authx/dynamic.go | 38 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/pkg/authprovider/authx/dynamic.go b/pkg/authprovider/authx/dynamic.go index cff03147d..28ec59298 100644 --- a/pkg/authprovider/authx/dynamic.go +++ b/pkg/authprovider/authx/dynamic.go @@ -3,7 +3,7 @@ package authx import ( "fmt" "strings" - "sync" + "sync/atomic" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/replacer" @@ -30,8 +30,8 @@ type Dynamic struct { Input string `json:"input" yaml:"input"` // (optional) target for the dynamic secret Extracted map[string]interface{} `json:"-" yaml:"-"` // extracted values from the dynamic secret fetchCallback LazyFetchSecret `json:"-" yaml:"-"` - m *sync.Mutex `json:"-" yaml:"-"` // mutex for lazy fetch - fetched bool `json:"-" yaml:"-"` // flag to check if the secret has been fetched + fetched *atomic.Bool `json:"-" yaml:"-"` // atomic flag to check if the secret has been fetched + fetching *atomic.Bool `json:"-" yaml:"-"` // atomic flag to prevent recursive fetch calls error error `json:"-" yaml:"-"` // error if any } @@ -70,7 +70,8 @@ func (d *Dynamic) UnmarshalJSON(data []byte) error { // Validate validates the dynamic secret func (d *Dynamic) Validate() error { - d.m = &sync.Mutex{} + d.fetched = &atomic.Bool{} + d.fetching = &atomic.Bool{} if d.TemplatePath == "" { return errkit.New(" template-path is required for dynamic secret") } @@ -97,9 +98,7 @@ func (d *Dynamic) Validate() error { func (d *Dynamic) SetLazyFetchCallback(callback LazyFetchSecret) { d.fetchCallback = func(d *Dynamic) error { err := callback(d) - d.fetched = true if err != nil { - d.error = err return err } if len(d.Extracted) == 0 { @@ -184,9 +183,15 @@ func (d *Dynamic) applyValuesToSecret(secret *Secret) error { // GetStrategy returns the auth strategies for the dynamic secret func (d *Dynamic) GetStrategies() []AuthStrategy { - if !d.fetched { + if d.fetched.Load() { + if d.error != nil { + return nil + } + } else { + // Try to fetch if not already fetched _ = d.Fetch(true) } + if d.error != nil { return nil } @@ -203,12 +208,23 @@ func (d *Dynamic) GetStrategies() []AuthStrategy { // Fetch fetches the dynamic secret // if isFatal is true, it will stop the execution if the secret could not be fetched func (d *Dynamic) Fetch(isFatal bool) error { - d.m.Lock() - defer d.m.Unlock() - if d.fetched { - return nil + if d.fetched.Load() { + return d.error } + + // Try to set fetching flag atomically + if !d.fetching.CompareAndSwap(false, true) { + // Already fetching, return current error + return d.error + } + + // We're the only one fetching, call the callback d.error = d.fetchCallback(d) + + // Mark as fetched and clear fetching flag + d.fetched.Store(true) + d.fetching.Store(false) + if d.error != nil && isFatal { gologger.Fatal().Msgf("Could not fetch dynamic secret: %s\n", d.error) } From d2cf69aebb8cefbd450399357ecfa739e9d6b88b Mon Sep 17 00:00:00 2001 From: Dwi Siswanto <25837540+dwisiswant0@users.noreply.github.com> Date: Mon, 22 Sep 2025 23:39:24 +0700 Subject: [PATCH 132/135] feat(fuzz): enhance `MultiPartForm` with metadata APIs (#6486) * feat(fuzz): enhance `MultiPartForm` with metadata APIs * add `SetFileMetadata`/`GetFileMetadata` APIs for file metadata management. * implement RFC-2046 boundary validation (max 70 chars). * add boundary validation in `Decode` method. * fix `filesMetadata` initialization. * fix mem leak by removing defer from file reading loop. * fix file metadata overwriting by storing first file's metadata instead of last. Closes #6405, #6406 Signed-off-by: Dwi Siswanto * chore(fuzz): satisfy lint errs Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto --- pkg/fuzz/dataformat/multipart.go | 64 +++++++++++-- pkg/fuzz/dataformat/multipart_test.go | 128 ++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 10 deletions(-) diff --git a/pkg/fuzz/dataformat/multipart.go b/pkg/fuzz/dataformat/multipart.go index 483814f28..a82ffcce0 100644 --- a/pkg/fuzz/dataformat/multipart.go +++ b/pkg/fuzz/dataformat/multipart.go @@ -27,7 +27,29 @@ var ( // NewMultiPartForm returns a new MultiPartForm encoder func NewMultiPartForm() *MultiPartForm { - return &MultiPartForm{} + return &MultiPartForm{ + filesMetadata: make(map[string]FileMetadata), + } +} + +// SetFileMetadata sets the file metadata for a given field name +func (m *MultiPartForm) SetFileMetadata(fieldName string, metadata FileMetadata) { + if m.filesMetadata == nil { + m.filesMetadata = make(map[string]FileMetadata) + } + + m.filesMetadata[fieldName] = metadata +} + +// GetFileMetadata gets the file metadata for a given field name +func (m *MultiPartForm) GetFileMetadata(fieldName string) (FileMetadata, bool) { + if m.filesMetadata == nil { + return FileMetadata{}, false + } + + metadata, exists := m.filesMetadata[fieldName] + + return metadata, exists } // IsType returns true if the data is MultiPartForm encoded @@ -125,16 +147,24 @@ func (m *MultiPartForm) ParseBoundary(contentType string) error { if m.boundary == "" { return fmt.Errorf("no boundary found in the content type") } + + // NOTE(dwisiswant0): boundary cannot exceed 70 characters according to + // RFC-2046. + if len(m.boundary) > 70 { + return fmt.Errorf("boundary exceeds maximum length of 70 characters") + } + return nil } // Decode decodes the data from MultiPartForm format func (m *MultiPartForm) Decode(data string) (KV, error) { + if m.boundary == "" { + return KV{}, fmt.Errorf("boundary not set, call ParseBoundary first") + } + // Create a buffer from the string data b := bytes.NewBufferString(data) - // The boundary parameter should be extracted from the Content-Type header of the HTTP request - // which is not available in this context, so this is a placeholder for demonstration. - // You will need to pass the actual boundary value to this function. r := multipart.NewReader(b, m.boundary) form, err := r.ReadForm(32 << 20) // 32MB is the max memory used to parse the form @@ -153,30 +183,44 @@ func (m *MultiPartForm) Decode(data string) (KV, error) { result.Set(key, values[0]) } } - m.filesMetadata = make(map[string]FileMetadata) + + if m.filesMetadata == nil { + m.filesMetadata = make(map[string]FileMetadata) + } + for key, files := range form.File { fileContents := []interface{}{} + var fileMetadataList []FileMetadata + for _, fileHeader := range files { file, err := fileHeader.Open() if err != nil { return KV{}, err } - defer func() { - _ = file.Close() - }() buffer := new(bytes.Buffer) if _, err := buffer.ReadFrom(file); err != nil { + _ = file.Close() + return KV{}, err } + _ = file.Close() + fileContents = append(fileContents, buffer.String()) - m.filesMetadata[key] = FileMetadata{ + fileMetadataList = append(fileMetadataList, FileMetadata{ ContentType: fileHeader.Header.Get("Content-Type"), Filename: fileHeader.Filename, - } + }) } + result.Set(key, fileContents) + + // NOTE(dwisiswant0): store the first file's metadata instead of the + // last one + if len(fileMetadataList) > 0 { + m.filesMetadata[key] = fileMetadataList[0] + } } return KVOrderedMap(&result), nil } diff --git a/pkg/fuzz/dataformat/multipart_test.go b/pkg/fuzz/dataformat/multipart_test.go index a649ee13a..1493e20d3 100644 --- a/pkg/fuzz/dataformat/multipart_test.go +++ b/pkg/fuzz/dataformat/multipart_test.go @@ -240,3 +240,131 @@ Python assert.Contains(t, documentsArray, "fake_pdf_content_1") assert.Contains(t, documentsArray, "fake_pdf_content_2") } + +func TestMultiPartForm_SetGetFileMetadata(t *testing.T) { + form := NewMultiPartForm() + metadata := FileMetadata{ + ContentType: "image/jpeg", + Filename: "test.jpg", + } + form.SetFileMetadata("avatar", metadata) + + // Test GetFileMetadata for existing field + retrievedMetadata, exists := form.GetFileMetadata("avatar") + assert.True(t, exists) + assert.Equal(t, metadata.ContentType, retrievedMetadata.ContentType) + assert.Equal(t, metadata.Filename, retrievedMetadata.Filename) + + // Test GetFileMetadata for non-existing field + _, exists = form.GetFileMetadata("nonexistent") + assert.False(t, exists) +} + +func TestMultiPartForm_FilesMetadataInitialization(t *testing.T) { + form := NewMultiPartForm() + assert.NotNil(t, form.filesMetadata) + + metadata := FileMetadata{ + ContentType: "text/plain", + Filename: "test.txt", + } + form.SetFileMetadata("file", metadata) + + retrievedMetadata, exists := form.GetFileMetadata("file") + assert.True(t, exists) + assert.Equal(t, metadata, retrievedMetadata) +} + +func TestMultiPartForm_BoundaryValidation(t *testing.T) { + form := NewMultiPartForm() + + // Test valid boundary + err := form.ParseBoundary("multipart/form-data; boundary=testboundary") + assert.NoError(t, err) + assert.Equal(t, "testboundary", form.boundary) + + // Test missing boundary + err = form.ParseBoundary("multipart/form-data") + assert.Error(t, err) + assert.Contains(t, err.Error(), "no boundary found") + + // Test boundary too long (over 70 characters) + longBoundary := "multipart/form-data; boundary=" + string(make([]byte, 71)) + for i := range longBoundary[len("multipart/form-data; boundary="):] { + longBoundary = longBoundary[:len("multipart/form-data; boundary=")+i] + "a" + longBoundary[len("multipart/form-data; boundary=")+i+1:] + } + + err = form.ParseBoundary(longBoundary) + assert.Error(t, err) + assert.Contains(t, err.Error(), "boundary exceeds maximum length") +} + +func TestMultiPartForm_DecodeRequiresBoundary(t *testing.T) { + form := NewMultiPartForm() + + // Decode should fail if boundary is not set + _, err := form.Decode("some data") + assert.Error(t, err) + assert.Contains(t, err.Error(), "boundary not set") +} + +func TestMultiPartForm_MultipleFilesMetadata(t *testing.T) { + form := NewMultiPartForm() + form.boundary = "----WebKitFormBoundaryMultiFileTest" + + // Test with multiple files having the same field name + multipartData := `------WebKitFormBoundaryMultiFileTest +Content-Disposition: form-data; name="documents"; filename="file1.txt" +Content-Type: text/plain + +content1 +------WebKitFormBoundaryMultiFileTest +Content-Disposition: form-data; name="documents"; filename="file2.txt" +Content-Type: text/plain + +content2 +------WebKitFormBoundaryMultiFileTest-- +` + + decoded, err := form.Decode(multipartData) + require.NoError(t, err) + + // Verify files are decoded correctly + documents := decoded.Get("documents") + require.NotNil(t, documents) + documentsArray, ok := documents.([]interface{}) + require.True(t, ok) + require.Len(t, documentsArray, 2) + assert.Contains(t, documentsArray, "content1") + assert.Contains(t, documentsArray, "content2") + + // Verify metadata for the field exists (should be from the first file) + metadata, exists := form.GetFileMetadata("documents") + assert.True(t, exists) + assert.Equal(t, "text/plain", metadata.ContentType) + assert.Equal(t, "file1.txt", metadata.Filename) // Should be from first file, not last +} + +func TestMultiPartForm_SetFileMetadataWithNilMap(t *testing.T) { + form := &MultiPartForm{} + + // SetFileMetadata should handle nil filesMetadata + metadata := FileMetadata{ + ContentType: "application/pdf", + Filename: "document.pdf", + } + form.SetFileMetadata("doc", metadata) + + // Should be able to retrieve the metadata + retrievedMetadata, exists := form.GetFileMetadata("doc") + assert.True(t, exists) + assert.Equal(t, metadata, retrievedMetadata) +} + +func TestMultiPartForm_GetFileMetadataWithNilMap(t *testing.T) { + form := &MultiPartForm{} + + // GetFileMetadata should handle nil filesMetadata gracefully + _, exists := form.GetFileMetadata("anything") + assert.False(t, exists) +} From 8ea5061f5e43b5ac731f6fa91e7022f30bf67537 Mon Sep 17 00:00:00 2001 From: Nakul Bharti Date: Mon, 22 Sep 2025 22:44:10 +0530 Subject: [PATCH 133/135] jira: hotfix for Cloud to use /rest/api/3/search/jql (#6489) * jira: hotfix for Cloud to use /rest/api/3/search/jql in FindExistingIssue; add live test verifying v3 endpoint * jira: fix Cloud v3 search response handling (no total); set Self from base * fix lint error * tests(jira): apply De Morgan to satisfy staticcheck QF1001 --- pkg/reporting/trackers/jira/jira.go | 43 +++++++++++++ pkg/reporting/trackers/jira/jira_test.go | 80 ++++++++++++++++++++++++ 2 files changed, 123 insertions(+) diff --git a/pkg/reporting/trackers/jira/jira.go b/pkg/reporting/trackers/jira/jira.go index ebfbfd9cb..1fe02b085 100644 --- a/pkg/reporting/trackers/jira/jira.go +++ b/pkg/reporting/trackers/jira/jira.go @@ -437,6 +437,49 @@ func (i *Integration) FindExistingIssue(event *output.ResultEvent, useStatus boo jql = fmt.Sprintf("%s AND status != \"%s\"", jql, i.options.StatusNot) } + // Hotfix for Jira Cloud: use Enhanced Search API (v3) to avoid deprecated v2 path + if i.options.Cloud { + params := url.Values{} + params.Set("jql", jql) + params.Set("maxResults", "1") + params.Set("fields", "id,key") + + req, err := i.jira.NewRequest("GET", "/rest/api/3/search/jql"+"?"+params.Encode(), nil) + if err != nil { + return jira.Issue{}, err + } + + var searchResult struct { + Issues []struct { + ID string `json:"id"` + Key string `json:"key"` + } `json:"issues"` + IsLast bool `json:"isLast"` + NextPageToken string `json:"nextPageToken"` + } + + resp, err := i.jira.Do(req, &searchResult) + if err != nil { + var data string + if resp != nil && resp.Body != nil { + d, _ := io.ReadAll(resp.Body) + data = string(d) + } + return jira.Issue{}, fmt.Errorf("%w => %s", err, data) + } + + if len(searchResult.Issues) == 0 { + return jira.Issue{}, nil + } + first := searchResult.Issues[0] + base := strings.TrimRight(i.options.URL, "/") + return jira.Issue{ + ID: first.ID, + Key: first.Key, + Self: fmt.Sprintf("%s/rest/api/3/issue/%s", base, first.ID), + }, nil + } + searchOptions := &jira.SearchOptionsV2{ MaxResults: 1, // if any issue exists, then we won't create a new one Fields: []string{"summary", "description", "issuetype", "status", "priority", "project"}, diff --git a/pkg/reporting/trackers/jira/jira_test.go b/pkg/reporting/trackers/jira/jira_test.go index d9b27adf7..a2e94290b 100644 --- a/pkg/reporting/trackers/jira/jira_test.go +++ b/pkg/reporting/trackers/jira/jira_test.go @@ -1,6 +1,8 @@ package jira import ( + "net/http" + "os" "strings" "testing" @@ -9,9 +11,23 @@ import ( "github.com/projectdiscovery/nuclei/v3/pkg/model/types/stringslice" "github.com/projectdiscovery/nuclei/v3/pkg/output" "github.com/projectdiscovery/nuclei/v3/pkg/reporting/trackers/filters" + "github.com/projectdiscovery/retryablehttp-go" "github.com/stretchr/testify/require" ) +type recordingTransport struct { + inner http.RoundTripper + paths []string +} + +func (rt *recordingTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if rt.inner == nil { + rt.inner = http.DefaultTransport + } + rt.paths = append(rt.paths, req.URL.Path) + return rt.inner.RoundTrip(req) +} + func TestLinkCreation(t *testing.T) { jiraIntegration := &Integration{} link := jiraIntegration.CreateLink("ProjectDiscovery", "https://projectdiscovery.io") @@ -188,3 +204,67 @@ Priority: {{if eq .Severity "critical"}}{{.Severity | upper}}{{else}}{{.Severity require.Contains(t, result, "CRITICAL") }) } + +// Live test to verify SearchV2JQL hits /rest/api/3/search/jql when creds are provided via env +func TestJiraLive_SearchV2UsesJqlEndpoint(t *testing.T) { + jiraURL := os.Getenv("JIRA_URL") + jiraEmail := os.Getenv("JIRA_EMAIL") + jiraAccountID := os.Getenv("JIRA_ACCOUNT_ID") + jiraToken := os.Getenv("JIRA_TOKEN") + jiraPAT := os.Getenv("JIRA_PAT") + jiraProjectName := os.Getenv("JIRA_PROJECT_NAME") + jiraProjectID := os.Getenv("JIRA_PROJECT_ID") + jiraStatusNot := os.Getenv("JIRA_STATUS_NOT") + jiraCloud := os.Getenv("JIRA_CLOUD") + + if jiraURL == "" || (jiraPAT == "" && jiraToken == "") || (jiraEmail == "" && jiraAccountID == "") || (jiraProjectName == "" && jiraProjectID == "") { + t.Skip("live Jira test skipped: missing JIRA_* env vars") + } + + statusNot := jiraStatusNot + if statusNot == "" { + statusNot = "Done" + } + + isCloud := !strings.EqualFold(jiraCloud, "false") && jiraCloud != "0" + + rec := &recordingTransport{} + rc := retryablehttp.NewClient(retryablehttp.DefaultOptionsSingle) + rc.HTTPClient.Transport = rec + + opts := &Options{ + Cloud: isCloud, + URL: jiraURL, + Email: jiraEmail, + AccountID: jiraAccountID, + Token: jiraToken, + PersonalAccessToken: jiraPAT, + ProjectName: jiraProjectName, + ProjectID: jiraProjectID, + IssueType: "Task", + StatusNot: statusNot, + HttpClient: rc, + } + + integration, err := New(opts) + require.NoError(t, err) + + event := &output.ResultEvent{ + Host: "example.com", + Info: model.Info{ + Name: "Nuclei Live Verify", + SeverityHolder: severity.Holder{Severity: severity.Low}, + }, + } + + _, _ = integration.FindExistingIssue(event, true) + + var hitSearchV2 bool + for _, p := range rec.paths { + if strings.HasSuffix(p, "/rest/api/3/search/jql") { + hitSearchV2 = true + break + } + } + require.True(t, hitSearchV2, "expected client to call /rest/api/3/search/jql, got paths: %v", rec.paths) +} From 202524283bfd6b0a1d736f061252a29ba620e63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Tue, 23 Sep 2025 16:43:08 +0300 Subject: [PATCH 134/135] fix headless template loading logic when `-dast` option is enabled --- pkg/catalog/loader/loader.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/catalog/loader/loader.go b/pkg/catalog/loader/loader.go index 40fbaa482..b1887149d 100644 --- a/pkg/catalog/loader/loader.go +++ b/pkg/catalog/loader/loader.go @@ -580,7 +580,14 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ // check if the template is a DAST template // also allow global matchers template to be loaded if parsed.IsFuzzing() || parsed.Options.GlobalMatchers != nil && parsed.Options.GlobalMatchers.HasMatchers() { - loadTemplate(parsed) + if len(parsed.RequestsHeadless) > 0 && !store.config.ExecutorOptions.Options.Headless { + stats.Increment(templates.ExcludedHeadlessTmplStats) + if config.DefaultConfig.LogAllEvents { + store.logger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath) + } + } else { + loadTemplate(parsed) + } } } else if len(parsed.RequestsHeadless) > 0 && !store.config.ExecutorOptions.Options.Headless { // donot include headless template in final list if headless flag is not set From 93be3b829160e2952a854c62ffa60cafef93b989 Mon Sep 17 00:00:00 2001 From: Nakul Bharti Date: Wed, 24 Sep 2025 01:12:43 +0530 Subject: [PATCH 135/135] fix: improve cleanup in parallel execution (#6490) --- .../common/protocolstate/memguardian.go | 17 +- .../common/protocolstate/memguardian_test.go | 123 ++++++++++++++ pkg/protocols/http/request.go | 8 + pkg/protocols/http/request_test.go | 155 ++++++++++++++++++ pkg/testutils/testutils.go | 5 + 5 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 pkg/protocols/common/protocolstate/memguardian_test.go diff --git a/pkg/protocols/common/protocolstate/memguardian.go b/pkg/protocols/common/protocolstate/memguardian.go index 8a0d9699a..2f31f4ca7 100644 --- a/pkg/protocols/common/protocolstate/memguardian.go +++ b/pkg/protocols/common/protocolstate/memguardian.go @@ -28,12 +28,17 @@ func StartActiveMemGuardian(ctx context.Context) { memTimer = time.NewTicker(memguardian.DefaultInterval) ctx, cancelFunc = context.WithCancel(ctx) - go func() { + + ticker := memTimer + go func(t *time.Ticker) { + if t == nil { + return + } for { select { case <-ctx.Done(): return - case <-memTimer.C: + case <-t.C: if IsLowOnMemory() { _ = GlobalGuardBytesBufferAlloc() } else { @@ -41,7 +46,7 @@ func StartActiveMemGuardian(ctx context.Context) { } } } - }() + }(ticker) } func StopActiveMemGuardian() { @@ -52,9 +57,13 @@ func StopActiveMemGuardian() { return } + if cancelFunc != nil { + cancelFunc() + cancelFunc = nil + } if memTimer != nil { memTimer.Stop() - cancelFunc() + memTimer = nil } } diff --git a/pkg/protocols/common/protocolstate/memguardian_test.go b/pkg/protocols/common/protocolstate/memguardian_test.go new file mode 100644 index 000000000..7306b81e2 --- /dev/null +++ b/pkg/protocols/common/protocolstate/memguardian_test.go @@ -0,0 +1,123 @@ +package protocolstate + +import ( + "context" + "testing" + "time" + + "github.com/projectdiscovery/utils/memguardian" + "github.com/stretchr/testify/require" + "github.com/tarunKoyalwar/goleak" +) + +// TestMemGuardianGoroutineLeak tests that MemGuardian properly cleans up goroutines +func TestMemGuardianGoroutineLeak(t *testing.T) { + defer goleak.VerifyNone(t, + goleak.IgnoreAnyContainingPkg("go.opencensus.io/stats/view"), + goleak.IgnoreAnyContainingPkg("github.com/syndtr/goleveldb"), + goleak.IgnoreAnyContainingPkg("github.com/go-rod/rod"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/interactsh/pkg/server"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/ratelimit"), + ) + + // Initialize memguardian if not already initialized + if memguardian.DefaultMemGuardian == nil { + var err error + memguardian.DefaultMemGuardian, err = memguardian.New() + require.NoError(t, err, "Failed to initialize memguardian") + } + + t.Run("StartAndStopMemGuardian", func(t *testing.T) { + // Test that starting and stopping memguardian doesn't leak goroutines + ctx := context.Background() + + // Start MemGuardian + StartActiveMemGuardian(ctx) + require.NotNil(t, memTimer, "memTimer should be initialized") + require.NotNil(t, cancelFunc, "cancelFunc should be initialized") + + // Give it a moment to start + time.Sleep(10 * time.Millisecond) + + // Stop MemGuardian + StopActiveMemGuardian() + + // Give goroutine time to exit + time.Sleep(20 * time.Millisecond) + + // Verify cleanup + require.Nil(t, memTimer, "memTimer should be nil after stop") + require.Nil(t, cancelFunc, "cancelFunc should be nil after stop") + }) + + t.Run("MultipleStartStop", func(t *testing.T) { + // Test multiple start/stop cycles + for i := 0; i < 3; i++ { + ctx := context.Background() + StartActiveMemGuardian(ctx) + time.Sleep(5 * time.Millisecond) + StopActiveMemGuardian() + time.Sleep(10 * time.Millisecond) + } + }) + + t.Run("ContextCancellation", func(t *testing.T) { + // Test that context cancellation properly stops the goroutine + ctx, cancel := context.WithCancel(context.Background()) + + StartActiveMemGuardian(ctx) + require.NotNil(t, memTimer, "memTimer should be initialized") + + // Cancel context to trigger goroutine exit + cancel() + + // Give it time to process cancellation + time.Sleep(20 * time.Millisecond) + + // Clean up + StopActiveMemGuardian() + time.Sleep(10 * time.Millisecond) + }) + + t.Run("IdempotentStart", func(t *testing.T) { + // Test that multiple starts don't create multiple goroutines + ctx := context.Background() + + StartActiveMemGuardian(ctx) + firstTimer := memTimer + + // Start again - should be idempotent + StartActiveMemGuardian(ctx) + require.Equal(t, firstTimer, memTimer, "memTimer should be the same") + require.NotNil(t, cancelFunc, "cancelFunc should still be set") + + StopActiveMemGuardian() + time.Sleep(10 * time.Millisecond) + }) +} + +// TestMemGuardianReset tests resetting global state +func TestMemGuardianReset(t *testing.T) { + defer goleak.VerifyNone(t, + goleak.IgnoreAnyContainingPkg("go.opencensus.io/stats/view"), + goleak.IgnoreAnyContainingPkg("github.com/syndtr/goleveldb"), + goleak.IgnoreAnyContainingPkg("github.com/go-rod/rod"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/interactsh/pkg/server"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/ratelimit"), + ) + + // Ensure clean state + StopActiveMemGuardian() + time.Sleep(20 * time.Millisecond) // Allow any existing goroutines to exit + + // Test that we can start after stop + ctx := context.Background() + StartActiveMemGuardian(ctx) + + // Verify it started + require.NotNil(t, memTimer, "memTimer should be initialized after restart") + + // Clean up + StopActiveMemGuardian() + time.Sleep(10 * time.Millisecond) // Allow cleanup +} diff --git a/pkg/protocols/http/request.go b/pkg/protocols/http/request.go index c6e3de4d9..37c78eacd 100644 --- a/pkg/protocols/http/request.go +++ b/pkg/protocols/http/request.go @@ -292,6 +292,8 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV select { case <-input.Context().Done(): + close(tasks) + workersWg.Wait() return input.Context().Err() default: } @@ -299,6 +301,8 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV // resize check point - nop if there are no changes if shouldFollowGlobal && spmHandler.Size() != request.options.Options.PayloadConcurrency { if err := spmHandler.Resize(input.Context(), request.options.Options.PayloadConcurrency); err != nil { + close(tasks) + workersWg.Wait() return err } // if payload concurrency increased, add more workers @@ -322,6 +326,8 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV break } request.options.Progress.IncrementFailedRequestsBy(int64(generator.Total())) + close(tasks) + workersWg.Wait() return err } if input.MetaInput.Input == "" { @@ -331,6 +337,8 @@ func (request *Request) executeParallelHTTP(input *contextargs.Context, dynamicV if request.isUnresponsiveAddress(updatedInput) { // skip on unresponsive host no need to continue spmHandler.Cancel() + close(tasks) + workersWg.Wait() return nil } select { diff --git a/pkg/protocols/http/request_test.go b/pkg/protocols/http/request_test.go index b547d91b5..9eb7b100e 100644 --- a/pkg/protocols/http/request_test.go +++ b/pkg/protocols/http/request_test.go @@ -7,8 +7,10 @@ import ( "net/http/httptest" "sync/atomic" "testing" + "time" "github.com/stretchr/testify/require" + "github.com/tarunKoyalwar/goleak" "github.com/projectdiscovery/nuclei/v3/pkg/model" "github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity" @@ -371,3 +373,156 @@ func TestExecuteParallelHTTP_SkipOnUnresponsiveFromCache(t *testing.T) { require.NoError(t, err) require.Equal(t, int32(0), atomic.LoadInt32(&matches), "expected no matches when host is marked unresponsive") } + +// TestExecuteParallelHTTP_GoroutineLeaks uses goleak to detect goroutine leaks in all HTTP parallel execution scenarios +func TestExecuteParallelHTTP_GoroutineLeaks(t *testing.T) { + defer goleak.VerifyNone(t, + goleak.IgnoreAnyContainingPkg("go.opencensus.io/stats/view"), + goleak.IgnoreAnyContainingPkg("github.com/syndtr/goleveldb"), + goleak.IgnoreAnyContainingPkg("github.com/go-rod/rod"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/interactsh/pkg/server"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/interactsh/pkg/client"), + goleak.IgnoreAnyContainingPkg("github.com/projectdiscovery/ratelimit"), + goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).drain"), + goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).compactionError"), + goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).mpoolDrain"), + goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).tCompaction"), + goleak.IgnoreAnyFunction("github.com/syndtr/goleveldb/leveldb.(*DB).mCompaction"), + ) + + options := testutils.DefaultOptions + testutils.Init(options) + defer testutils.Cleanup(options) + + // Test Case 1: Normal execution with StopAtFirstMatch + t.Run("StopAtFirstMatch", func(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(10 * time.Millisecond) + _, _ = fmt.Fprintf(w, "test response") + })) + defer ts.Close() + + req := &Request{ + ID: "parallel-stop-first-match", + Method: HTTPMethodTypeHolder{MethodType: HTTPGet}, + Path: []string{"{{BaseURL}}/test?param={{payload}}"}, + Threads: 4, + Payloads: map[string]interface{}{ + "payload": []string{"1", "2", "3", "4", "5", "6", "7", "8"}, + }, + Operators: operators.Operators{ + Matchers: []*matchers.Matcher{{ + Part: "body", + Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher}, + Words: []string{"test response"}, + }}, + }, + StopAtFirstMatch: true, + } + + executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{ + ID: "parallel-stop-first-match", + Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"}, + }) + + err := req.Compile(executerOpts) + require.NoError(t, err) + + metadata := make(output.InternalEvent) + previous := make(output.InternalEvent) + ctxArgs := contextargs.NewWithInput(context.Background(), ts.URL) + + err = req.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) {}) + require.NoError(t, err) + }) + + // Test Case 2: Unresponsive host scenario + t.Run("UnresponsiveHost", func(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = fmt.Fprintf(w, "response") + })) + defer ts.Close() + + req := &Request{ + ID: "parallel-unresponsive", + Method: HTTPMethodTypeHolder{MethodType: HTTPGet}, + Path: []string{"{{BaseURL}}/test?param={{payload}}"}, + Threads: 3, + Payloads: map[string]interface{}{ + "payload": []string{"1", "2", "3", "4", "5"}, + }, + Operators: operators.Operators{ + Matchers: []*matchers.Matcher{{ + Part: "body", + Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher}, + Words: []string{"response"}, + }}, + }, + } + + executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{ + ID: "parallel-unresponsive", + Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"}, + }) + executerOpts.HostErrorsCache = &fakeHostErrorsCache{} + + err := req.Compile(executerOpts) + require.NoError(t, err) + + metadata := make(output.InternalEvent) + previous := make(output.InternalEvent) + ctxArgs := contextargs.NewWithInput(context.Background(), ts.URL) + + err = req.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) {}) + require.NoError(t, err) + }) + + // Test Case 3: Context cancellation scenario + t.Run("ContextCancellation", func(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(200 * time.Millisecond) + _, _ = fmt.Fprintf(w, "response") + })) + defer ts.Close() + + req := &Request{ + ID: "parallel-context-cancel", + Method: HTTPMethodTypeHolder{MethodType: HTTPGet}, + Path: []string{"{{BaseURL}}/test?param={{payload}}"}, + Threads: 3, + Payloads: map[string]interface{}{ + "payload": []string{"1", "2", "3", "4", "5"}, + }, + Operators: operators.Operators{ + Matchers: []*matchers.Matcher{{ + Part: "body", + Type: matchers.MatcherTypeHolder{MatcherType: matchers.WordsMatcher}, + Words: []string{"response"}, + }}, + }, + } + + executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{ + ID: "parallel-context-cancel", + Info: model.Info{SeverityHolder: severity.Holder{Severity: severity.Low}, Name: "test"}, + }) + + err := req.Compile(executerOpts) + require.NoError(t, err) + + metadata := make(output.InternalEvent) + previous := make(output.InternalEvent) + + ctx, cancel := context.WithCancel(context.Background()) + ctxArgs := contextargs.NewWithInput(ctx, ts.URL) + + go func() { + time.Sleep(50 * time.Millisecond) + cancel() + }() + + err = req.ExecuteWithResults(ctxArgs, metadata, previous, func(event *output.InternalWrappedEvent) {}) + require.Error(t, err) + require.Equal(t, context.Canceled, err) + }) +} diff --git a/pkg/testutils/testutils.go b/pkg/testutils/testutils.go index 5f791c2c1..521654c45 100644 --- a/pkg/testutils/testutils.go +++ b/pkg/testutils/testutils.go @@ -33,6 +33,11 @@ func Init(options *types.Options) { _ = protocolinit.Init(options) } +// Cleanup cleans up the protocols and their configurations +func Cleanup(options *types.Options) { + protocolstate.Close(options.ExecutionId) +} + // DefaultOptions is the default options structure for nuclei during mocking. var DefaultOptions = &types.Options{ Metrics: false,